39 바이트 얻기
이것은 Dennis와 JonathanFrech 가 별도로 찾은 39 바이트 솔루션을 얻는 방법에 대한 설명입니다 . 또는 오히려, 그것은 내 실제 경로보다 훨씬 더 좋은 방법으로 어떻게 뒷받침으로 대답에 도달 할 수 있는지 설명합니다.
n=0
exec"print n;n=n+2^-(n+2^n)%3;"*400
약간 덜 골퍼하고 더 많은 양의 스패닝으로 작성하면 다음과 같습니다.
n=0
for _ in range(400):
print n
n=(n+2)^(-((n+2)^n))%3
비트 패리티
우리는 내에서 아이디어로 시작하는 47 바이트 솔루션 출력 형태의 모든 숫자 까지 계산 하고 하나의도의 전체 수를 만드는 패리티 비트이다.n=2*k+bk0,1,...,399b
의 작성하자 par(x)에 대한 비트 패리티 의 x배타적 논리합 (이다 ^)의 모든 비트를 x. 짝수의 1 비트가 있으면 0이고 (숫자는 사악함) 홀수의 1 비트가 있으면 1입니다. 들어 n=2*k+b우리가 가진, par(n) = par(k)^b그래서 악을 달성하기 위해 par(n)==0우리가 필요로하는을 b=par(k)의 마지막 비트 즉, n앞의 비트의 비트 패리티가 될 수 있습니다.
골프에서 나의 첫번째 노력은 표현에 있었다 par(k), 처음으로 직접시 와 bin(k).count('1')%2함께 다음과 비트 조작 .
패리티 업데이트
그럼에도 불구하고 짧은 표현은 없었습니다. 대신 작업 할 정보가 더 많다는 것을 인식하는 데 도움이되었습니다. 현재 숫자의 비트 패리티를 계산하는 대신
k ----> par(k)
우리가 증가로 우리는 비트 패리티를 업데이트 할 수 있습니다 k에 k+1.
k ----> par(k)
|
v
k+1 ----> par(k+1)
즉, 카운트 업 k=0,1,2,...하기 때문에 매번 처음부터 계산하지 않고 현재 비트 패리티를 유지하면됩니다. 비트 패리티 업데이트 par(k+1)^par(k)에서가 뒤집혀 비트 수이다 패리티 k에 k+1해당이다 par((k+1)^k).
par(k+1) ^ par(k) = par((k+1)^k)
par(k+1) = par(k) ^ par((k+1)^k)
형태 (k+1)^k
이제 계산해야합니다 par((k+1)^k). 계산 비트 패리티는 우리가 해결하려는 문제이기 때문에 우리가 아무데도없는 것처럼 보일 수 있습니다. 그러나 숫자 는 2의 거듭 제곱보다 1이 적은 (k+1)^k것으로 표현되며 숫자는 비트 핵에서1,3,7,15,.. 종종 사용됩니다 . 왜 그런지 보자.
우리가 증가 할 때 k, 이진 캐리의 효과는 마지막 0과 모든 1것을 오른쪽 으로 뒤집는 것 0입니다. 예를 들어k=43=0b101011
**
101011 (43)
+ 1
------
= 101100 (44)
101011 (43)
^101100 (44)
------
= 000111 (77)
캐리를 발생시키는 열은로 표시되어 *있습니다. 이것은 a로 1변경하고의 0캐리 비트를 전달합니다.이 비트 1는 0in k에 도달 할 때까지 왼쪽으로 전파 되고로 변경됩니다 1. 더 왼쪽에있는 비트는 영향을받지 않습니다. 그래서, k^(k+1)비트 위치를 확인 변경 k에 k+1, 그것은 가장 오른쪽의 위치를 발견 0하고 1그 오른쪽에의합니다. 즉, 변경된 비트는 접미사를 형성하므로 결과는 0 다음에 하나 이상의 1이옵니다. 선행 0이 없으면 1, 11, 111, 1111, ...2의 거듭 제곱보다 작은 이진수가 있습니다 .
컴퓨팅 par((k+1)^k)
이제 (k+1)^k로 제한됨을 이해 1,3,7,15,...했으므로 이러한 숫자의 비트 패리티를 계산하는 방법을 찾으십시오. 여기에, 유용한 사실은 즉 1,2,4,8,16,...다른 모듈 3사이 1와 2, 이후 2==-1 mod 3. 따라서 1,3,7,15,31,63...모듈로를 3사용하면 1,0,1,0,1,0...비트 패리티가됩니다. 완전한!
따라서 업데이트를 다음 par(k+1) = par(k) ^ par((k+1)^k)과 같이 수행 할 수 있습니다.
par(k+1) = par(k) ^ ((k+1)^k)%3
b패리티를 저장하는 변수로 사용 하면 다음과 같습니다.
b^=((k+1)^k)%3
코드 작성
코드에서 이것을 함께 퍼팅, 우리는 시작 k과 패리티 비트 b에 모두 0다음 반복적으로 인쇄, n=2*k+b업데이트 b=b^((k+1)^k)%3및 k=k+1.
46 바이트
k=b=0
exec"print 2*k+b;b^=(k+1^k)%3;k+=1;"*400
온라인으로 사용해보십시오!
우리는 주위에 괄호를 제거 k+1에 ((k+1)^k)%3있기 때문에 파이썬의 우선 순위는 첫째, 어쨌든 보이는 이상한로 추가한다.
코드 개선
단일 변수로 직접 작업하고 직접 n=2*k+b업데이트를 수행하면 더 잘할 수 있습니다 . 에 k+=1해당합니다 n+=2. 그리고 업데이트는에 b^=(k+1^k)%3해당합니다 n^=(k+1^k)%3. 여기서 k=n/2업데이트하기 전에 n.
44 바이트
n=0
exec"print n;n^=(n/2+1^n/2)%3;n+=2;"*400
온라인으로 사용해보십시오!
우리는 다시 작성하여 단축 할 수 있습니다 n/2+1^n/2(이것을 기억하십시오 (n/2+1)^n/2)
n/2+1 ^ n/2
(n+2)/2 ^ n/2
(n+2 ^ n)/2
/2마지막 비트를 제거 하므로 xoring 전이나 후에 비트를 제거해도 문제가되지 않습니다. 그래서 우리는 있습니다 n^=(n+2^n)/2%3. 우리는 모듈이 있음을 지적하여 다른 바이트를 저장할 수 있습니다 3, /2에 해당 *2에 해당 -즉 지적, n+2^n분할은 바닥없이 실제 반감이도 그래서입니다. 이것은 준다n^=-(n+2^n)%3
41 바이트
n=0
exec"print n;n^=-(n+2^n)%3;n+=2;"*400
온라인으로 사용해보십시오!
마지막으로, 우리는 작업을 결합 할 수 있습니다 n^=c;n+=2로 n=(n+2)^c, 여기서 c조금이다. 이것은 ^c마지막 비트에서만 작동 하고 마지막 비트 +2는 신경 쓰지 않기 때문에 작동하므로 작업이 출퇴근합니다. 다시, 우선 순위는 parens를 생략하고 씁니다 n=n+2^c.
39 바이트
n=0
exec"print n;n=n+2^-(n+2^n)%3;"*400
온라인으로 사용해보십시오!