C ++에서 골프를 할 때 어떤 일반적인 팁이 있습니까? 저는 C ++에 다소 특정한 코드 골프 문제에 적용될 수있는 아이디어를 찾고 있습니다 (예 : "댓글 제거"는 답이 아닙니다). 답변 당 하나의 팁을 게시하십시오.
C ++에서 골프를 할 때 어떤 일반적인 팁이 있습니까? 저는 C ++에 다소 특정한 코드 골프 문제에 적용될 수있는 아이디어를 찾고 있습니다 (예 : "댓글 제거"는 답이 아닙니다). 답변 당 하나의 팁을 게시하십시오.
답변:
삼항 조건 연산자는 ?:
종종 단순한를위한에서 스탠드로 사용할 수 있습니다 if
- else
상당한 비용 절감에서 문.
다음과 같이 대체 lvalue를 선택하는 데 사용할 수 있다는 점에서 특별한 가치가 있습니다.
#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;
}
e
및 중 하나에 대한 참조 o
입니다. 이것은이 연산자가 lvalue 일 수 없기 때문에 작동하지 않는 c에서이 연산자의 작동 방식과 다릅니다.
std::endl
하는 '\n'
것으로 교체하십시오
일부 컴파일러 (예 : GCC)는 다중 문자 상수를 지원 합니다. 큰 정수 값이 필요한 경우 몇 문자를 절약 할 수 있습니다. 예:
int n=' ';
값은 구현별로 다릅니다. 일반적으로의 값 'ab'
은 256*'a'+'b'
또는 'a'+256*'b'
입니다. 따옴표 사이에 최대 4자를 지정할 수 있습니다.
내가 찾은 것 :
true
부울 표현식에서 0이 아닌 값이 평가 되고 부울 x&&y
을 x*y
처리 할 때 평가 된다는 사실 활용
(x!=0 && y!=0)
~에 평가하다
(x*y)
아래에서 지적한 것처럼 오버플로를 알아야합니다.
x!=0 && y!=0
입니다. 그러나 곱셈을 사용할 때는 오버플로에주의해야합니다. 32 비트 정수를 사용할 때 x = y = 65536 (및 2의 거듭 제곱의 여러 조합)도 x * y = 0이 됩니다.
&&
단락 동작이 *
부족합니다. 예를 들어, 당신은 대체 할 수 없습니다 i++!=0&&j++!=0
와 i++*j++
.
다음 유형을 사용하십시오.
u64, s64, u32, s32 (or int)
반복적 인 단어 / 유형의 경우 다음을 사용하십시오 #defines
.
#define a while
while
여분의 10자를 보충하기 위해 많이 사용 하는 경우에만 가치가 있습니다 . ( 약 4 )
가능하면, 변경 &&
및 ||
행 &
과 |
각각.
간단한 if 문을 사용할 때 :
if(<condition>)<stuff>;
다음으로 변경할 수 있습니다.
<condition>?<stuff>:<any single letter variable>;
캐릭터를 저장합니다.
절에 둘 이상의 명령문이있는 상황에서 여는 중괄호 대신 쉼표 연산자를 사용하면 몇 개의 문자를 절약 할 수 있습니다.
if(c){x=1;cout<<"Hi";y=2;}else{x=2;cout<<"Bye";y=3;}
vs.
if(c)x=1,cout<<"Hi",y=2;else x=2,cout<<"Bye",y=3;###
일반 IF에 2 개의 문자가 저장되거나 IF / ELSE에 3 개의 문자가 저장되었습니다.
C와 C ++의 구별 점으로 C ++에서 쉼표 식의 결과는 lvalue ... FWIW로 사용될 수 있습니다.
배열 요소는 다음과 같은 대신 메모리에 서로 직접 저장되므로 :
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;
가독성을 위해 위의 어느 것도 골라 내지 않지만 포인터를 명시 적으로 사용하면 많은 공간을 절약 할 수 있습니다.
for(int* i=array; i<array+25*25; i++)
? 그런 다음 하나의 변수 만 추적하면됩니다.
분명한 것이지만 많은 표준 라이브러리를 사용하고 있으면 using namespace std;
몇 문자를 절약 할 수 있습니다.
using std::name;
더 짧을 수 있습니다.
std::
5 회 이상 사용하는 경우에만 문자를 저장합니다 .
10의 큰 거듭 제곱을 쓰는 대신 e 표기법을 사용하십시오 . 예를 들어, a=1000000000
보다 깁니다 a=1e9
. a=1e9+24
보다 나은 다른 숫자로 확장 할 수 있습니다 a=1000000024
.
1e9/x
동일하지 않다 1000000000/x
거나 int(1e9)/x
.
?:
트루 블록에서 표현식없이 삼항 연산자 를 사용할 수 있습니다 (바이트 저장).
#include <iostream>
int foo()
{
std::cout << "Foo\n";
}
int main()
{
1?foo():0; // if (true) foo()
0?:foo(); // if (!false) foo()
}
이것은 GCC에 따라 다르며 다른 컴파일러로 확장 할 수 있습니다.
G ++ bits/stdc++.h
에서는 미리 컴파일 된 헤더가 다른 모든 헤더로 구성됩니다. import
다른 두 가지 가 필요 하면 이것을 사용할 수 있습니다.
이것은 http://en.cppreference.com/w/cpp/header에 나열된 모든 헤더입니다 .
길이 순서대로 정렬됩니다.
그들 중 일부는 이미보다 길고 bits/stdc++.h
일부는 C ++ 17 지원이 필요합니다. 일부는 TIO G ++에서 지원하지 않습니다 (알지 못하는 이유로). 우리가 가지고있는 걸 걸러 내십시오 :
그들 중 일부는 더 짧은 것으로 대체 될 수 있습니다. 필요한 것을 바꿀 수 있는지 바이너리 검색 만하면됩니다. 특히:
cstdio -> ios (-3 bytes)
algorithm -> regex (-4 bytes)
vector -> queue (-1 byte)
string -> map (-3 bytes)
bitset -> regex (-1 byte)
numeric -> random (-1 byte)
부울에 대한 산술 연산 :
이기는하지만, 비록 일지라도
a*=b>0?.5:-.5
~보다 낫다
if(b>0)a*=.5;else a*=-.5;
그것은만큼 좋지 않다
a*=(b>0)-.5
또한 많이 사용되는 모든 항목에 #define을 사용하십시오. 유형 이름이 필요하지 않기 때문에 종종 함수를 사용하는 것보다 짧습니다.
가능한 많은 것들을 결합하십시오 :
a+=a--;
와 같다
a=2*a-1;
이외의 유형의 경우 int
이를 함수 인수로 사용하면 비용이 많이들 수 있습니다. 그러나 일반적인 람다는 (C ++ 14?) 도입되었으며 람다는 템플릿이 될 수 있습니다- auto
인수 유형에 사용 하면 바이트를 절약 할 수 있습니다. 비교:
double f(double x, double y)
[](auto x, auto y)
C ++에서 배열 입력을 받아들이는 아마 가장 좋은 방법입니다 - 일반 람다도 수용 반복자에 매우 편리합니다 [](auto a, auto z)
, a
그리고 z
로 전달 begin()
하고 end()
등 배열 / 벡터 / 목록 /의.
작업 "다음 숫자 빼기"에 대한 코드 골프에서의 첫 번째 시도에서 나는 함수 (58 바이트)에서 시작했다.
int f(int N, int P){int F;for(F=N;P;F-=++N,P--);return F;}
그런 다음 람다로 이동하고 초기화를 for
(53) 밖으로 이동하여 안전한 5 바이트
[](int N,int P){int F=N;for(;P;F-=++N,P--);return F;}
그리고 마침내에서 for
로 전환 한 후 while
51 바이트를 얻었습니다.
[](int N,int P){int F=N;while(P--)F-=++N;return F;}
ungolfed 테스트 코드는 다음과 같습니다.
#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;}
두 개의 정수 변수 a와 b를 바꾸려면
a^=b^=a^=b;
표준 방식보다 5자를 절약하여 사용할 수 있습니다.
a+=b;
b=a-b;
a-=b;
,t
이전에 생성 된 정수에서 t=a;a=b;b=t;
이미보다 3 바이트 짧았을 것 a+=b;b=a-b;a-=b;
입니다. 아직도, 당신 a^=b^=a^=b;
은 그것보다 짧아서, +1입니다. 나는 C ++을 모르지만 실제로 작동합니다 . Java 코드 골퍼로서 슬프게도 거기에서 작동하지 않는 것 같습니다 . :(
a^=b;b^=a;a^=b;
에서 잘 작동하고있다.
a^=b;b^=a;a^=b;
실제로 작동하지만 ,t
+ 보다 깁니다 t=a;a=b;b=t;
. 여기에 주제가 없기 때문에 Java를 언급하는 것에 대해 죄송합니다. 그러나 C ++ codegolfers에 대한 유용한 팁!
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;}
사용하지 마십시오 string("")
, 사용 ""
. 8 바이트를 절약합니다.
"" + 'a'
인 char* + char
반면, 포인터 또한 인 std::string("") + 'a'
이다 std::string + char
- 문자열 연결. string()
작동 할 것이다.