सी ++ में गोल्फ के लिए टिप्स


48

C ++ में गोल्फिंग के लिए आपके पास क्या सामान्य सुझाव हैं? मैं ऐसे विचारों की तलाश कर रहा हूं, जो सामान्य रूप से C ++ के लिए कुछ हद तक विशिष्ट कोड गोल्फ समस्याओं के लिए लागू किए जा सकते हैं (उदाहरण के लिए "टिप्पणियां हटाएं" एक उत्तर नहीं है)। कृपया प्रति उत्तर एक टिप पोस्ट करें।


4
सी में गोल्फिंग के लिए कई युक्तियां C ++ पर भी लागू होती हैं, इसलिए कृपया मान लें कि पाठक उस प्रश्न से परिचित हैं; केवल यहाँ पोस्ट अगर आपके पास कुछ है जो एक मान्य सी गोल्फ टिप नहीं है।
टॉबी स्पाईट

@TobySpeight शायद, क्योंकि उनके पास प्रश्न आईडी के अलावा एक ही यूआरएल है।
NoOneIsHere

C और C ++, भले ही 'गोल्फिंग' प्रकार न हों, सही और आसान हैं (यदि कोई C ++ के सही सबसेट को
मानता है

जवाबों:


24

टर्नरी सशर्त ऑपरेटर ?:को अक्सर सरल के लिए एक स्टैंड के रूप में इस्तेमाल किया जा सकता है if- elseकाफी बचत पर बयान।

यह इस बात का विशेष महत्व है कि इसका उपयोग वैकल्पिक स्वरों को चुनने के लिए किया जा सकता है

#include <iostream>
#include <cstdlib>
int main(int c, char**v){
  int o=0,e=0,u;
  while(--c) ((u=atoi(v[c]))%2?o:e)+=u;
  std::cout << "Sum of odds " << o <<std::endl
            << "Sum of evens " << e <<std::endl;
}

कोड अभी तक नहीं चला है, लेकिन मुझे नहीं लगता कि यह आपके कहने के तरीके पर काम करता है। ((u = atoi (v [c]))% 2? o: e) + = u कुछ भी नहीं करता है लेकिन मूल्य यू को बाईं ओर अभिव्यक्ति में जोड़ने के लिए जो मान ओ या ई प्राप्त करता है, लेकिन चर ओ और ई अपरिवर्तित रहें, इसलिए वे हमेशा देखेंगे कि क्या हैपन्स देखने के लिए कोड की जांच करें। आपको इसे काम करने के लिए एड्रेन्स का उपयोग करना चाहिए
बोगडान अलेक्जेंड्रू

4
@BogdanAlexandru Er ... इसे चलाते हैं। यह वास्तव में काम करता है। निक्षिप्त अभिव्यक्ति के मूल्य एक के लिए एक संदर्भ या अन्य है eऔर o। ध्यान दें कि यह अलग है कि यह ऑपरेटर c में कैसे काम करता है जहां यह चाल काम नहीं करती है क्योंकि यह एक अंतराल नहीं हो सकता है।
dmckee 13

इसके std::endlसाथ बदलें '\n'5 चार्ट
मुकुल कुमार

3
@ मुकुलकुमार खैर, हाँ। लेकिन इस टिप को प्रदर्शित करने के उद्देश्यों के लिए मैंने स्पष्टता के लिए टर्नरी-सशर्त अन-गोल्फ को छोड़कर सब कुछ छोड़ दिया।
dmckee

22

कभी-कभी आप इस तथ्य का उपयोग करके दो पात्रों को बचा सकते हैं कि स्थिर भंडारण अवधि चर (जिसमें विशेष रूप से सभी वैश्विक गुंजाइश चर शामिल हैं) स्वचालित रूप से शुरुआत में शून्य-आरंभिक हैं (स्वचालित चर के विपरीत जहां आपके पास ऐसी कोई गारंटी नहीं है)। इसलिए इसके बजाय

int main()
{
  int a=0;
  // ...
}

तुम लिख सकते हो

int a;
int main()
{
  // ...
}

+1 लेकिन निश्चित रूप से बुरा व्यवहार
mondlos

@mondlos: गोल्फ मूल रूप से बुरे अभ्यास का अर्थ है।
celtschk

15

कुछ संकलक (जैसे GCC) मल्टी-कैरेक्टर स्थिरांक का समर्थन करते हैं । जब बड़े पूर्णांक मान की आवश्यकता होती है तो यह कुछ वर्णों को सहेज सकता है। उदाहरण:

int n='  ';

मूल्य कार्यान्वयन-विशिष्ट है। आमतौर पर का मान 'ab'है 256*'a'+'b'या 'a'+256*'b'। आप उद्धरण चिह्नों के बीच 4 वर्ण तक निर्दिष्ट कर सकते हैं।


3
जीसीसी? आपका मतलब जी ++ है ?
नाथन उस्मान

6
@ जॉर्ज एडिसन: जीसीसी जीएनयू कंपाइलर कलेक्शन के लिए खड़ा है , जिसमें सी, सी ++, गो, आदि के लिए इसके सभी सीमांतों को शामिल किया गया है
जोए एडम्स

@ जोए: मुझे पता है, लेकिन यह जीएनयू सी कंपाइलर का भी नाम है।
नाथन उस्मान

25
@ जॉर्ज: जीएनयू सी कंपाइलर को जीसीसी कहा जाता है, जीसीसी नहीं।
fredoverflow

और साथ ही याद रख सकता है कि, मैं भूल सकता था।

12

एक जो मुझे काम मिला:

इस तथ्य का लाभ उठाते हुए कि गैर-शून्य मान trueबूलियन अभिव्यक्तियों में मूल्यांकन करते हैं, और यह बूलियन के साथ व्यवहार करते समय x&&yमूल्यांकन करता हैx*y

(x!=0 && y!=0)

का मूल्यांकन करता है

(x*y)

आपको बस ओवरफ्लो के बारे में पता होना चाहिए, जैसा कि नीचे बताया गया है।


2
तकनीकी रूप से, यह है x!=0 && y!=0। लेकिन गुणा का उपयोग करते समय आपको ओवरफ्लो से सावधान रहने की आवश्यकता होती है। 32-बिट पूर्णांक x = y = 65536 (और दो की शक्तियों के कई अन्य संयोजनों) का उपयोग करते समय भी x * y = 0 होगा
मार्टिन एंडर

हाँ य़ह सही हैं। मैंने इसे एक द्वि-आयामी सरणी सीमा जाँच के रूप में उपयोग किया: codegolf.stackexchange.com/a/37571/31477 जहाँ यह कोई बात नहीं थी। मैं उन बिंदुओं को संपादित करूंगा।
बाल्ड्रिक

1
ध्यान दें कि &&एक शॉर्ट-सर्किट व्यवहार है जिसमें *कमी है। उदाहरण के लिए, आप के i++!=0&&j++!=0साथ प्रतिस्थापित नहीं कर सकते i++*j++
celtschk

@celtschk हाँ, अच्छी बात है। लेकिन अगर आप पूरी तरह से बूलियन बीजगणित कर रहे हैं, तो यह काम करता है
बाल्ड्रिक

11

निम्न प्रकारों का उपयोग करें:

u64, s64, u32, s32 (or int)

दोहराव वाले शब्दों / प्रकारों के लिए, उपयोग करें #defines:

#define a while

यह केवल इसके लायक है यदि आप whileअतिरिक्त 10 वर्णों के लिए बहुत अधिक उपयोग करते हैं । ( लगभग )


1
प्रकार u64, s64, u32 और s32 C ++ का हिस्सा नहीं हैं। वे आपके संकलक का एक गैर-मानक विस्तार हो सकता है (मैंने उन्हें कभी नहीं देखा है, हालांकि)।
celtschk

5
इन दो युक्तियों को दो अलग-अलग उत्तरों में रखा जाएगा ताकि वे व्यक्तिगत रूप से मतदान कर सकें।
ट्राइकोप्लाक्स


10

जब संभव हो, को बदलने &&और ||करने के लिए &और |क्रमशः।

बयान का उपयोग करते समय सरल है:

if(<condition>)<stuff>;

इसे बदला जा सकता है:

<condition>?<stuff>:<any single letter variable>;

जो एक चरित्र बचाता है।



8

खुले और करीबी ब्रेसिज़ के बदले में अल्पविराम ऑपरेटर का उपयोग करके कुछ पात्रों को बचाया जा सकता है, यदि आपके पास ऐसी स्थिति है जहां आपके खंडों में एक से अधिक कथन हैं:

if(c){x=1;cout<<"Hi";y=2;}else{x=2;cout<<"Bye";y=3;}

बनाम

if(c)x=1,cout<<"Hi",y=2;else x=2,cout<<"Bye",y=3;###

दो अक्षर एक सादे IF पर, या एक IF / ELSE के लिए तीन कुल सहेजे गए।

C और C ++ के बीच अंतर के एक बिंदु के रूप में, C ++ में एक अल्पविराम अभिव्यक्ति का परिणाम एक अंतराल के रूप में इस्तेमाल किया जा सकता है ... FWIW।


7

चूँकि सरणी तत्व एक दूसरे के बाद सीधे मेमोरी में संग्रहीत होते हैं, इस तरह से कुछ के बजाय:

for(int x = 0; x < 25; x++) {
    for(int y = 0; y < 25; y++)
        array[x][y] = whatever;
}

आप ऐसा कुछ कर सकते हैं:

int* pointer = array;
for(int i = 0; i < 25*25; i++, pointer++)
    *pointer = whatever;

स्पष्ट रूप से पठनीयता के लिए उपरोक्त दोनों में से कोई भी गोल्फ नहीं है, लेकिन स्पष्ट रूप से पॉइंटर्स का उपयोग करने से आप बहुत सारे स्थान बचा सकते हैं।


मत भूलो कि आप उस सभी व्हाट्सएप को काट सकते हैं! (पूरी तरह से अलग टिप, लेकिन उल्लेख किया जाना चाहिए)
स्टोकैस्टिक

@stokastic उदाहरण केवल तकनीक का उपयोग करने के लिए प्रदर्शित करने के लिए, गोल्फ होने के लिए नहीं हैं।
Stuntddude

6
क्यों नहीं for(int* i=array; i<array+25*25; i++)? फिर आपको केवल एक चर का ट्रैक रखना होगा।
लुकास

6

एक स्पष्ट एक, लेकिन यह आप मानक पुस्तकालय का एक बहुत उपयोग कर रहे हैं, using namespace std;कुछ अक्षर बचा सकता है।


5
यदि आप केवल एक ही नाम का उपयोग करते हैं, लेकिन वह अक्सर using std::name;, हालांकि, छोटा हो सकता है।
celtschk

10
यह केवल पात्रों को बचाता है यदि आप std::पांच या अधिक बार उपयोग करते हैं ।
nyuszika7h

6

यह याद रखना उपयोगी है कि a[i]जैसा है वैसा ही है *(a+i)

दो चरित्र बचत के a[0]साथ बदलें *a। इसके अलावा, a[i][0]के बराबर है *a[i]और a[0][i]नीचे सिकुड़ता है i[*a]। इसलिए यदि आप 0अपने एरे में एक इंडेक्स को हार्ड-कोडिंग कर रहे हैं , तो बेहतर तरीका मौजूद है।


5

10 की बड़ी शक्तियों को लिखने के बजाय, ई नोटेशन का उपयोग करें । उदाहरण के लिए, a=1000000000की तुलना में लंबा है a=1e9। इसे अन्य नंबरों की तरह बढ़ाया जा सकता है जैसे a=1e9+24कि इससे बेहतर है a=1000000024


1
ध्यान दें कि यह बिल्कुल समतुल्य नहीं है, उपयोग करने से पहले पूर्णांक प्रकारों में डालने की आवश्यकता है। उदाहरण के लिए या के 1e9/xरूप में ही नहीं है । 1000000000/xint(1e9)/x
user202729

5

आप ?:सच्चे-ब्लॉक में किसी भी भाव के बिना टर्नरी ऑपरेटर का उपयोग कर सकते हैं (यह एक बाइट बचाता है)

#include <iostream>

int foo()
{
    std::cout << "Foo\n";
}

int main()
{
    1?foo():0;  // if (true) foo()
    0?:foo();   // if (!false) foo()
}

इसे यहां देखें


5
यह एक GNU एक्सटेंशन प्रतीत होता है और C ++ मानक में नहीं। https://gcc.gnu.org/onbuildocs/gcc-4.4.4/gcc/Conditionals.html#Conditionals
छत

? आर foo (): 0; // if (r) फू () यह ठीक है ;;;; लेकिन इस आर के लिए ?: फू (); मुझे नहीं पता कि
RosLuP

5

शॉल्डर हेडर

यह जीसीसी विशिष्ट है, यह अन्य संकलक के लिए एक्स्टेंसिबल हो सकता है।

शीर्ष लेख।

G ++ bits/stdc++.hमें पहले से तैयार हेडर में अन्य सभी हेडर होते हैं। यदि आपको import2 अलग-अलग लोगों की आवश्यकता है तो आप इसका उपयोग कर सकते हैं।

शॉल्डर हेडर।

यह सभी हेडर http://en.cppreference.com/w/cpp/header पर सूचीबद्ध हैं :

लंबाई के बढ़ते क्रम में क्रमबद्ध।

उनमें से कुछ पहले से अधिक लंबे हैं bits/stdc++.h, और उनमें से कुछ को C ++ 17 समर्थन की आवश्यकता है। कुछ अन्य टीआईओ जी ++ द्वारा समर्थित नहीं हैं (उन कारणों के लिए जिन्हें मैं नहीं जानता हूं)। उन्हें हमारे पास फ़िल्टर करें:

ऐसा हो सकता है कि उनमें से कुछ को छोटे लोगों द्वारा प्रतिस्थापित किया जा सकता है। बस द्विआधारी खोज कि क्या आप की जरूरत है प्रतिस्थापित किया जा सकता है। विशेष रूप से:

cstdio -> ios        (-3 bytes)
algorithm -> regex   (-4 bytes)
vector -> queue      (-1 byte)
string -> map        (-3 bytes)
bitset -> regex      (-1 byte)
numeric -> random    (-1 byte)

4

#importइसके बजाय #includeआपको एक और बाइट देता है।

इसके अलावा, #importहेडर और हेडर के बीच का स्पेस कैरेक्टर जरूरी नहीं है:

#include <map>
// vs
#import<map>

और अगर आपको stdlibहेडर से कुछ चाहिए , तो आप इसके बजाय STL कंटेनर (बेहतर setया map) के साथ किसी भी हेडर को आयात कर सकते हैं cstdlib


3

बूलियन पर अंकगणितीय ऑपरेशन:

हालांकि

a*=b>0?.5:-.5

से बेहतर है

if(b>0)a*=.5;else a*=-.5;

यह उतना अच्छा नहीं है

a*=(b>0)-.5

इसके अलावा, #define का उपयोग किसी भी चीज पर किया जाता है जो बहुत उपयोग की जाती है। यह अक्सर फ़ंक्शन का उपयोग करने से छोटा होता है, क्योंकि टाइप नाम आवश्यक नहीं हैं।

जितना हो सके चीजों को मिलाएं:

a+=a--;

के समान है

a=2*a-1;

हालांकि आपके उदाहरण सही हैं, लेकिन xएक अपरिवर्तनशील व्यवहार को लागू करने से सावधान रहें जब एक लवल्यू के x++रूप में और एक रवैल के रूप में उपयोग किया जाता है । अपरिभाषित व्यवहार और अनुक्रम बिंदु
सीलिंगकैट

हाँ संभव + ए - ए; ने
अविभाजित

3

सस्ते टेम्प्लेट के रूप में सामान्य लैम्ब्डा का प्रयोग करें

के अलावा अन्य प्रकार के लिए int, उन्हें फ़ंक्शन तर्क के रूप में उपयोग करना महंगा हो सकता है। हालाँकि, जेनेरिक लैम्ब्डा को पेश किया गया था (C ++ 14 में?) और किसी भी लैम्ब्डा को टेम्पलेट बनाने की अनुमति दें - autoतर्क प्रकारों का उपयोग करके बाइट्स बचा सकते हैं। की तुलना करें:

double f(double x, double y)
[](auto x, auto y)

सी ++ में सरणी आदानों स्वीकार करने के लिए शायद सबसे अच्छा तरीका है - सामान्य lambdas भी स्वीकार करने iterators के लिए बहुत सुविधाजनक है [](auto a, auto z), जहां aऔर zके रूप में पारित कर रहे हैं begin()और end()सरणी / वेक्टर / सूची / आदि की।


2

कार्य के लिए कोड गोल्फ में मेरे पहले प्रयास में "अगले नंबरों को घटाएं" मैंने फ़ंक्शन (58 बाइट्स) से शुरू किया है

int f(int N, int P){int F;for(F=N;P;F-=++N,P--);return F;}

फिर लैम्ब्डा में शिफ्टिंग के साथ 5 बाइट्स को सुरक्षित रखना और for(53) से बाहर निकलना।

[](int N,int P){int F=N;for(;P;F-=++N,P--);return F;}

और आखिरकार मुझे 51 बाइट्स से स्विच forकरने के बाद while:

[](int N,int P){int F=N;while(P--)F-=++N;return F;}

अनगुल्ड टेस्ट कोड कुछ इस तरह है:

#include <iostream>
int main(void)
{
    int N, P;
    std::cin >> N >> P;
    auto f = [](int N,int P)
    {
        int F = N;
        while (P--)
            F -= ++N;
        return F;
    };
    std::cout << f(N, P) << std::endl;
    return 0;
}

अपडेट करें:

वास्तव forमें एक ही लंबाई तक पहुँच सकते हैं while:

[](int N,int P){int F=N;for(;P--;F-=++N);return F;}

2

मुझे लगता है कि पार्टी के लिए देर से ...

यदि आप इसके बजाय 0 और 1 के बजाय -1 और 1 में एक अभिव्यक्ति को मोड़ना चाहते हैं:

int x;
if (a * 10 > 5)
    x = 1;
else
    x = -1;

यह करो:

int x = (a * 10 > 5) * 2 - 1;

यह उपयोग के आधार पर कुछ बाइट्स बचा सकता है।


इसके बजाय int x=(a*10>5)*2-1;, क्या आप ऐसा नहीं कर सकते int x=a*10>5?1:-1;, जो 1 बाइट से छोटा हो?
23

2

यदि आप दो पूर्णांक चर को स्वैप करना चाहते हैं a और b तब,

a^=b^=a^=b;

मानक तरीके की तुलना में 5 वर्णों को बचाने के लिए उपयोग किया जा सकता है

a+=b;
b=a-b;
a-=b;

1
उस मानक तरीके के बारे में। ,tपहले बनाए गए किलों में और फिर t=a;a=b;b=t;पहले से ही 3 बाइट्स कम होते a+=b;b=a-b;a-=b;। फिर भी, तुम्हारा a^=b^=a^=b;उससे भी छोटा है, इसलिए मुझसे १। मैं सी ++ नहीं जानता, लेकिन यह वास्तव में काम करता है । एक जावा कोड-गोल्फर के रूप में मैं दुखी हूँ यह वहाँ काम करने के लिए प्रतीत नहीं होता है । :(
केविन क्रूज़सेन

1
@KevinCruijssen हाँ, मुझे C ++ का उल्लेख करना चाहिए था, मैं जावा को ज्यादा नहीं जानता, लेकिन a^=b;b^=a;a^=b;जावा में ठीक काम कर रहा हूँ।
जोकर 00

1
C ++ का स्पष्ट रूप से उल्लेख करने की आवश्यकता नहीं है। ये सभी टिप्स C ++ के लिए हैं। :) एक जावा डेवलपर के रूप में मैं बस उत्सुक था अगर ऐसा ही कुछ जावा में किया जा सकता था, लेकिन स्पष्ट रूप से नहीं। a^=b;b^=a;a^=b;वास्तव में काम करता है, लेकिन ,t+ से अधिक लंबा है t=a;a=b;b=t;। जावा का उल्लेख करने के बारे में क्षमा करें, क्योंकि यह यहां से विषय है। लेकिन सी ++ कोडगॉल्फर्स के लिए अच्छा टिप!
केविन क्रूज़सेन

2

आयात करने के बजाय GCC बिल्डरों का उपयोग करें

यदि आप जीसीसी संकलक का उपयोग कर रहे हैं, तो यह कभी-कभी उनके अंतर्निहित कार्यों जैसे कि __builtin_putsया का उपयोग करने में मदद करता है __builtin_clz। उदाहरण के लिए,

44 बाइट्स:

int main(){__builtin_puts("Hello, world!");}`

50 बाइट्स:

#import<cstdio>
int main(){puts("Hello, world!");}

1

यदि आप C ++ 11 या नया कर रहे हैं (जो अब हमेशा होना चाहिए) auto, यदि संभव हो तो जटिल प्रकारों के लिए उपयोग करें ।

उदाहरण: 66 के बजाय 54 बाइट्स

#include<vector>
std::vector<int> f(std::vector<int> l){return l;}
#include<vector>
auto f(std::vector<int> l){return l;}

इसके अलावा, जैसा कि प्रदर्शन से कोई फर्क नहीं पड़ता, कुछ चुनौतियों के लिए std::listबस कुछ बाइट्स के लिए काम करना कम हो सकता है:

#include<list>
auto f(std::list<int> l){return l;}

1

में कार्य <algorithm>अक्सर गुजर की आवश्यकता है a.begin(),a.end()जो वास्तव में लंबा है, बजाय आप उपयोग कर सकते हैं &a[0],&*end(a)3 बाइट्स को बचाने के लिए अगर aहै vectorया string

sort(a.begin(),a.end());
sort(begin(a),end(a));
sort(&a[0],&*end(a));

0

उपयोग न करें string(""), उपयोग करें ""। यह 8 बाइट्स बचाता है।


यह बिल्कुल समकक्ष नहीं है। उदाहरण के लिए "" + 'a'है char* + char, जबकि जो सूचक है, std::string("") + 'a'है std::string + char- स्ट्रिंग संयोजन। string()काम करेगा।
user202729
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.