이 게시물의 목표 <all languages>
는 특정 팁이 아닌 쉽게 적용 할 수있는 모든 골프 팁을 수집 하는 것입니다.
논리가 대부분 의 언어에 적용될 수 있다는 답변 만 게시
답변 당 하나의 팁
<all languages>
이 게시물의 목표 <all languages>
는 특정 팁이 아닌 쉽게 적용 할 수있는 모든 골프 팁을 수집 하는 것입니다.
논리가 대부분 의 언어에 적용될 수 있다는 답변 만 게시
답변 당 하나의 팁
<all languages>
답변:
일반적으로 두 개의 후속 루프 또는 두 개의 중첩 루프를 하나로 병합 할 수 있습니다.
전에:
for (i=0; i<a; i++) foo();
for (i=0; i<b; i++) bar();
후:
for (i=0; i<a+b; i++) i<a?foo():bar();
foo
호출 a
시간, bar
호출 b
시간을. "after"에서 루프가 a+b
시간, 첫 번째 a
호출 foo
, 다음 호출을 실행하기 때문입니다 bar
.
for(y=0;y<Y;++y)for(x=0;x<X;++x)
종종이 될 수 for(i=0;i<X*Y;++i)
로 x
대체 i%X
하고 y
대체 i/X
.
명백한 것을 언급하기 위해 :
골프를 타는 경우 (특히 더 긴 프로그램으로 이어지는 어려운 문제) 너무 자주 다른 기본 옵션 을 시도하지 않고 선택한 경로를 고수 할 수 있습니다. 물론 전체 아이디어의 한 번에 또는 한 줄에 한두 줄씩 마이크로 골프를 할 수도 있지만 완전히 다른 해결책을 시도하지 않는 경우가 있습니다.
이것은 실제 알고리즘에서 벗어나 동일한 결과를 얻기 위해 적용 할 수있는 패턴을 찾는 많은 언어에서 J가 아닌 Hitting 495 (Kaprekar) 에서 특히 두드러졌습니다 .
단점은 아마도 같은 일을 십여 번 해결할 수 있다는 것입니다. 그러나 HQ9 +를 제외한 모든 언어에서 작동합니다 ( Hello World 를 출력하는 다른 방법을 찾는 것이 약간 쓸데없는 일임).
코드가 다양한 입력을 처리해야하는 경우 포괄적 인 테스트를 작성하여 매우 빠르게 실행할 수 있습니다. 이를 통해 한 번에 한 단계 씩 위험한 변형을 시도 할 수 있습니다. 그러면 골프는 악의적 인 의도로 리팩토링하는 것처럼됩니다.
예를 들어, 경우 A
와 것은 B
논리 값과 어느 정도 번호와 같은 언어를 취급 부울이다, A and (not B)
와 A>B
동일합니다. 예를 들어 파이썬에서
if A and not B:
foo()
와 같다:
if A>B:
foo()
B>A or foo()
이것을 표현하는 더 짧은 방법 일 것입니다. 부울 식의 게으른 평가를 활용하여 필요할 때만 계산하도록하십시오.
B>A or foo
평가 foo
합니다 B==A
. (오른쪽?)
대신에 x=1
이미 1과 같은 것을 찾으십시오.
예를 들어 함수의 반환 값 : printf("..");x=0;
-> x=!printf("..");
. 항상 부정 할 수 있거나 필요한 모든 것이 올바른 진실 가치 일 때 (그리고 1 또는 19인지 상관하지 않기 때문에) 0을 사용하는 것이 가장 쉽습니다.
~
에 대한 x+1
과x-1
이 트릭은 단항 비트 부정 연산자 ~
와 단항 정규 부정 연산자 가있는 언어에 적용됩니다 -
.
프로그램에 우연히 expression 표현식이 포함 된 경우 바이트를 저장하기 위해로 -x-1
대체 할 수 있습니다 ~x
. 이것은 너무 자주 발생하지는 않지만 -
두 표현식을 모두 부정 ( ) 하면 어떻게되는지 살펴보십시오 : x+1
equals -~x
! 마찬가지로, x-1
같습니다 ~-x
. (틸드 포인트가 어떤 방식인지 생각하십시오 : right is +
, left is -
.)
모든 언어에서 이러한 연산자가 있다고 생각할 수 있기 때문에 대부분의 연산자보다 우선 순위가 높습니다. 이를 통해 괄호를 절약 할 수 있습니다. 여기서 4 바이트를 절약하는 방법을 살펴보십시오.
(x+1)*(y-1) ==> -~x*~-y
해당 언어의 공백 규칙을 알고 있어야합니다. 일부 문장 부호 또는 다른 문자는 공백을 필요로하지 않을 수 있습니다. 이 Bourne 쉘 기능을 고려하십시오 .
f () { echo a; echo b; }
Bourne 쉘에서 ();
메타 문자이며 주변 공백이 필요하지 않습니다. 그러나 {}
단어이며 메타 문자 옆에 있지 않으면 공백이 필요합니다. 우리는 멀리 4 개 공간 옆에 골프 할 수 ();
있지만, 사이의 공간을 유지해야 {
하고 echo
.
f(){ echo a;echo b;}
에 커먼 리스프 와 PicoLisp , ()
메타 문자입니다. 이 코드를 고려하여 두 숫자의 평균을 찾으십시오.
(/ (+ a b) 2)
우리는 2 칸 떨어져 골프를 치를 수 있습니다.
(/(+ a b)2)
일부 언어에는 공백에 대해 이상하고 미묘한 규칙이 있습니다. 이 Ruby 프로그램은 정수 행의 합계와 곱을 인쇄합니다.
#!ruby -an
i=$F.map &:to_i
puts"#{i.reduce &:+} #{i.reduce &:*}"
각각 &
앞에 공간이 필요합니다. 루비에서 블록 매개 변수를 전달하는 위치 를 i=$F.map &:to_i
의미 합니다. 그러나 이항 연산자가있는 곳을 의미 합니다.i=$F.map(&:to_i)
&
i=$F.map&:to_i
i=$F.map.&(:to_i)
&
이 기묘함은 Perl 또는 Ruby와 같이 모호한 문장 부호를 사용하는 언어에서 발생합니다. 의심스러운 경우 REPL을 사용하거나 짧은 프로그램을 작성하여 공백 규칙을 테스트하십시오.
x = SomeLongFunctionName
x(somedata)
x(somemoredata)
etc
x
.
그 중 52 개가 있습니다. 그들 모두를 사용하십시오! 다른 접근법을 시도하고 길이를 비교하는 것을 두려워하지 마십시오. 사용 가능한 언어와 특정 단축키 / 라이브러리 기능을 알고 있어야합니다.
$
및 _
식별자로 사용할 수 있습니다.
@
T-SQL에서 유효한 변수 이름이므로 대신 사용하십시오 @a
.
조건부 연산자
bool ? condition_true : condition_false
IF 문 보다 문자 적으로 현명 합니다 .
if(a>b){r=a;}else{r=b;}
로 쓸 수 있습니다
r=a>b?a:b;
a&&b||c
대신 사용할 수 있습니다 . 약간 길지만 여전히보다 짧습니다 if
.
Iff
함수이지만 모든 인수를 평가해야합니다.
if(a ? b : c)
a&&b||c
반환 c
할 수 있음 참고 a
iff b
는 약간의 경우에 해당하지만 ^^
설명을 작성하면 코드의 각 부분을 다시 철저히 검토하고 특정 구절을 명시 적으로 작성할 때 생각과 선택을해야합니다. 그렇게함으로써 일부 바이트를 절약 할 수있는 다른 접근 방식이 가능하거나 잠재 의식적으로 가정 할 필요는없는 가정을했을 수 있습니다.
이 팁은 알고리즘 선택 질문 과 유사하며 완전히 새로운 것을 시도해보십시오 . 그러나 각 부분의 작동 방식을 실제로 적어 두는 단계가 대안을 인식하는 데 때로는 중요하다는 것을 알았습니다.
보너스로 설명을 포함한 답변이 다른 사용자에게는 더 흥미 롭기 때문에 공언 될 가능성이 높습니다.
당연히 들리는 것처럼 들리지만주의를 기울이면 실제로 아무 것도하지 않으면 서 몇 개의 문자를 "저장"할 수 있습니다!
Windows를 사용하는 경우, \r\n
그냥 \r
또는 대신 \n
Return 키를 눌렀을 때 입력 할 수 있습니다 . 줄당 바이트를 추가하십시오! 제어 문자를 돌려서 수행하지 않는 것을 다시 확인하십시오.
메모장 ++에서는 로 이동하여 모든 \r\n
줄 끝을 로 변환 할 수 있습니다 .\r
Edit > EOL Conversion > UNIX/OSX Format
또한 문자 수에 후행 공백을 포함시키지 마십시오! 코드의 맨 아래 줄에있는 줄 바꿈도 중요하지 않으므로 계산할 필요도 없습니다.
코드 골프는 질문을 이해하는 것만으로도 질문을 이해하는 것에 관한 것입니다 ( 다른 설정에서 암시하더라도 질문과 요청 되지 않은 내용).
명시 적으로 요청 된 것 이외의 입력은 처리 할 필요가 없습니다. 테스트 사례가 있고 일반적인 요구 사항이 없으면 코드는 해당 사례에서만 작동 할 수 있습니다. 기타.
약간의 경우가 될 수 있지만 때로는 유용 할 수 있습니다. m = 2 n -1이 적용되는 모든 숫자 는 가장 오른쪽에있는 n 비트가 1로 설정되어 있다는 사실에 의존합니다 .
따라서 7 10 == 00000111 2 , 15 10 == 00001111 2 , 31 10 == 00011111 2 등입니다.
트릭은 x&~m
입니다. 0과 (포함) 사이 x
가 아닐 때마다 true를 반환 m
하고 그렇지 않으면 false를 반환합니다. 다음으로 가장 짧은 등식 인 6 바이트를 절약 x>=0&&x<=m
하지만 m
2 n -1을 만족할 때만 작동합니다 .
새 변수 대신 함수 매개 변수 재사용
main(i){...
이제 값을 1 로 지정할 수 있습니다. 과제를 수행하십시오. 2 개의 문자가 저장되었습니다 ..
숫자를 저장하는 것보다 큼 / 낮음 :
//use:
if(n>9){A}else{B}
//instead of:
if(n<10){B}else{A}
단지에서 코드를 교환하는 것을 기억 if
받는 else
그들이 똑같은 일을 (또는 불평등의 측면을 전환) 할 것이다!
참고 : 이것은 10의 거듭 제곱과 그 부정에 적용 할 수 있습니다....-100, -10, 10, 100...
if(n>99999)
vsif(n<1e5)
하드 코딩 된 정수 값에 대해 검토 한 결과, 사용 >
하고 <
대신 >=
하고 <=
가능한있다. 예를 들어
if(x>24&&x<51)
사용하는 것보다 2 바이트 더 짧습니다
if(x>=25&&x<=50)
<1
대신 ==0
제로 체크 등 (또는 >0
대신 !=0
미러 확인 용).
x
정수라 는 것에 대한 메모를 추가해서는 안 됩니까?
부울 검사의 하나 이상의 인스턴스를 검사하기 위해 루프를 통해 실행하는 경우보다 효율적인 프로그램이 첫 번째 실제 값에서 루프를 종료하도록 만들 수 있습니다. 그러나 중단을 제거하고 모든 반복을 반복하면 코드가 더 짧아집니다.
int main() {
bool m = false;
int n = 1000;
for (int i = 0; i < n; i++) {
if (i >= 100) {
m = true;
break; // remove this line
}
}
return 0;
}
if
다음과 같은 경우에는 설명을 단순화 할 수도 있습니다 m|=i>=100
. ( 이 경우 에는 i>=100
to i>99
를 단순화 할 수도 있지만 여기서는 그다지 관련이 없습니다)
대부분의 언어에는 문자열을 일종의 토큰 주변의 문자열 배열로 나누는 방법이 있습니다. 문자열 당 추가 오버 헤드는 (적어도) 두 개의 문자열 구분 기호가 아닌 하나의 문자 토큰 사본이므로 길이가 언어 종속 임계 값에 도달하면 배열 리터럴보다 짧을 수밖에 없습니다.
예를 들어 GolfScript
["Foo""Bar""Baz""Quux"] # 23 chars
된다
"Foo
Bar
Baz
Quux"n/ # 20 chars
일부 언어의 경우 임계 값이 하나의 문자열만큼 낮습니다. 예를 들어 Java에서는
new String[]{"Foo"} // 19 chars
된다
"Foo".split("~") // 16 chars
%w{Foo Bar Baz Quux}
.
qw(Foo Bar Baz Quux)
문자열리스트가된다.
여러 표현식을 결합 할 때마다 언어에 대한 연산자 우선 순위 테이블을 확인하여 괄호를 저장하기 위해 항목을 재정렬 할 수 있는지 확인하십시오.
예 :
(a&b)&&c
더 괄호를 필요로하지 않는다 : a&b&&c
단지로 (a*b)+c
하지 않습니다.a+(b<<c)
로 다시 쓸 수 있습니다 a+b*2**c
. c
작은 정수 리터럴 인 경우 (<14)a<b&&c<d
와 a<b&c<d
(당신은 단락 회로 평가를 필요로하지 않는 한)당신이 경우 X
문 {
안쪽에 }
당신을위한 루프를, 당신은 이동할 수 있습니다 X-1
문 (
안쪽에 )
두 번째 세미콜론 이후에 대한 루프를 for(blah;blah;HERE)
3 바이트를 저장합니다. (쉼표를 사용하여 문장을 분리하십시오 ,
)
대신에
for(int i=0;i<9;){s+=s.length();println(i++);}
명령문 중 하나를 for 루프의 (
괄호 로 옮길 수 있고 다른 하나는 )
생략 할 수 있습니다
for(int i=0;i<9;println(i++))s+=s.length();
3 바이트를 절약하십시오 (@ETHProductions 덕분에 1 바이트 더 절약되었습니다)
간단히 말해서
대신에
for(blah;blah;){blah 1;blah 2;...;blah X}
당신이 이것으로 끝나도록 문장을 움직입니다.
for(blah;blah;blah 2,...,blah X)blah 1;
3 바이트를 저장
for
마지막 ;
~
에 대한 a-b-1
과a+b+1
뿐만 아니라 @Lynn 에 관한의 제안 x+1
→ -~x
; 그리고 x-1
→가~-x
, 당신은 또한 골프를 할 수 a-b-1
와 a+b+1
.
a-b-1 // 5 bytes
a+~b // 4 bytes
a+b+1 // 5 bytes
a-~b // 4 bytes
자주 사용하지 않는 팁처럼 보일 수 있습니다. ~x
대신 사용하는 것이 -x-1
자주 발생하지는 않지만 유용한 팁으로 볼 수 있도록 충분한 시간을 사용했습니다. 특히 배열 인덱싱을 사용하면 경우에 따라 위의 항목을 사용할 수 있습니다.
ands (또는이 경우 ors,이 경우 'all'을 'any'로 대체하십시오)로 묶인 긴 조건을 짜려고 할 때 생각해 낸 간단한 트릭.
예 :
if a>0 and a<10 and a+b==4 and a+3<1:
된다
if all([a>0,a<10,a+b==4,a+3<1]):
all(array-of-Booleans)
내장되어 있습니까?
[a>0,a<10,a+b==4,a+3<1].all?
if 10>a>0 and a+b==4>1>a+3:
컴파일러가 어떤 최적화를 보장하는지와 어떤 최적화 레벨을 사용하는지 알고 자유롭게 사용하십시오. 또한 성능이 문제 가되지 않아도 최적화를 사용하여 테스트 한 다음 컴파일러 플래그없이 기술적으로 유효한 코드이므로 한 문자 만 할인 할 수 있습니다 .
2 ^ n을 계산하려면 다음 Haskell 함수를 고려하십시오 (Haskell에 이미 내장 지수 연산자 또는 3 개가 있다는 사실을 무시 함) (23 자) :
p 0=1;p x=p(x-1)+p(x-1)
문제는-엄청나게 느리고, 기하 급수적으로 실행됩니다. 이로 인해 코드를 테스트 할 수 없거나 질문으로 인한 성능 제한이 실패 할 수 있습니다. 반복되는 함수 호출 (25 자)을 피하기 위해 임시 변수 또는 즉시 호출 된 함수 리터럴을 사용하려는 유혹이있을 수 있습니다.
p 0=1;p x=(\y->y+y)$p$x-1
그러나 컴파일러가 이미 그렇게 할 수 있으므로 -O
컴파일러 플래그로 설정 하면됩니다! 공통 하위 표현식을 수동으로 제거하기 위해 사이트 당 몇 개의 추가 문자를 소비하는 대신 전체 프로그램에서 총 1 문자 또는 2 문자에 대해 기본 최적화를 수행하도록 컴파일러에 지시하십시오.
p(x-1)*2
?
다소 명백하지만 ...
대입 연산자는 값을 반환합니다.
예를 들어, x에 y를 더한 다음 x가 다른 것보다 큰지 확인하려면 할 수 있습니다
if(25<x+=y)
대신에
x+=y;if(x>25)
또는 트리밍 후 문자열의 길이를 찾고 싶을 수도 있습니다.
strlen(s=trim(s))
오히려
s=trim(s);strlen(s)
a = (b=c)+1;
설정 b
에 c
설정 한 후,과 a
에 b+1
.
a=1+b=c
. 그리고 목록에 PHP와 JavaScript를 추가 할 수 있습니다.
=
연산자가 왼쪽보다 오른쪽보다 우선 순위가 높으므로 1+x=2
유효하며 다음과 같이 평가됩니다3
이것은 특히 폴리 글 로트에 유용 하지만 다른 문제에도 적용될 수 있습니다. 때로는 컴파일러 버그로 인해 1 바이트가 떨어지거나 구현 버그로 인해 몇 개의 문자를 저장하거나 실제로 최첨단 기능으로 점수를 향상시킬 수 있습니다.
가능하면 And / Or을 사용하여 확인한 경우 다중 / 중첩을 결합하십시오.
즉 :
if (a && (b || c)) {
}
대신에:
if (a) {
if (b) {
//Do Stuff
} elseif (c) {
//Do same stuff
}
}
&
더 많은 문자를 제거 하려면 비트 조건 ( ,`|)을 사용하십시오.
&
를 &&
제거하는 대신 비트 단위 를 사용하더라도 연산자 우선 순위를 엉망으로 만들고 괄호를 넣어야 작동합니다.