분기하지 마십시오


14

저수준 코드 최적화에 적당히 종사하는 사람은 분기의 위험에 대해 알고 있습니다. if 문, 루프 또는 선택문으로 분기 오류가 발생할 가능성은 끔찍한 시계 낭비입니다.

간단한 산술로 간단한 문제를 훨씬 더 잘 해결할 수 있으므로 그렇게하겠습니다.

다음 문제의 경우 모든 변수는 부호없는 32 비트 정수이며 유일하게 허용되는 코드는 다음 연산자 만 포함하는 일반 집합 명령문입니다.

+ addition
- subtraction
* multiplication
/ integer division, rounds down, division by 0 not allowed
% modulo
& binary and
| binary or
^ binary exclusive or
>> bitshift right
<< bitshift left

Logic operators, return 1 if the expression is true and 0 if it is false.
== equal
!= not equal
< less than
<= less than or equal
> greater than
>= greater than or equal

Set operator
=

모든 줄은 변수 식별자, 집합 연산자, 식으로 구성되어야합니다.

식에는 추가 집합 연산자가 포함되지 않지만 변수 식별자, 리터럴 숫자 및 괄호가 포함될 수 있습니다.

골프 점수는 운영자 수만 계산합니다.

예:

myvar = ( ( ( foo + 5 ) * bar ) % 7 ) == 3

5 명의 운영자가 있습니다.

솔루션에는 작성자가 알 수있는만큼 많은 변수가 포함될 수 있습니다.
설정되지 않은 변수는 value 0입니다.
오버 플로우와 언더 플로우 때문에, 모든 부정적인 번호는 언더, 허용 3 - 5된다 4294967294하더라도 큰 문의 일환으로.

작업 1 : 최대

두 값, AB, 상기 영역에 존재하게 RESULT변수 값 때 그 프로그램이 종료의 최대 함유한다.

작업 2 : 중앙값

세 값은, A, BC, 상기 영역에 존재하게 RESULT변수 값 때 그 프로그램이 종료의 중앙값을 포함한다.

작업 3 : 제곱근

A범위에 존재하는 하나의 값 은 프로그램이 종료 될 때 RESULT변수에 제곱근을 A내림하고 내림합니다.

하나 또는 두 개의 질문에 대한 답변 만 게시해도됩니다. 유효한 솔루션을 찾는 것이 어려울 수 있습니다.


단항 연산자는 어디에 있습니까? 나는 신경 쓰지 -않지만 ~멋질 수 있습니다 (무엇을 모르더라도).
John Dvorak

물론, 0xFFFF_FFFF_FFFF_FFFF ^ x하고 0 - x. 어떻게 잊어 버렸습니까?
John Dvorak

@JanDvorak 그것은 완전성 논리 !가 너무 간단 하지 않기 때문에 가장 짧은 설명을 만들었습니다 x == 0.
aaaaaaaaaaaa

0으로 나누는 동작은 무엇입니까?
John Dvorak

Mathematica에서 (a> b)는 True 또는 False를 반환합니다. Boole은 False를 0으로, True를 1로 변환합니다 Boole[a-b].
DavidC

답변:


5

작업 3, 23 ops

x = (A >> 16) + A / ((A >> 13) + 511) + 15
x = (x + A/x) >> 1
x = (x + A/x) >> 1
x = (x + A/x) >> 1
RESULT = x - (x > A/x)

다른 솔루션과 마찬가지로 Newton의 방법을 사용하여보다 정교하게 선택된 시드를 사용하십시오. 첫 번째 비트 A >> 16는 범위의 상단을 행복하게 A / ((A >> 13) + 511)유지하고 , 두 번째 비트 는 범위의 중간을 행복하게 유지하고 마지막 비트 15는 하단을 유지하며 0 오류로의 분할을 방지합니다 (15는 가능한 가장 큰 값 0으로 수렴하여 반으로 수렴 할 수 있음) 세 번 빼기 수정은 0과 같습니다). 입력 값 225, 275625, 82137969, 2908768489(및 근처 값)의 경우 초기 시드가 정확합니다. 범위의 모든 모서리 사례 (완전 제곱, 완전 제곱 + 1 및 완전 제곱-1) 0 .. 2**32-1가 테스트되었으며 정확합니다.

규칙에 대한 몇 가지 의견 :
오버플로 및 언더 플로가 허용되고 모든 음수가 언더 플로되므로 3-5는 더 큰 명령문의 일부로도 4294967294 입니다.

마지막 부분은 혁신 킬러의 것으로 밝혀졌습니다. 나는 처음에 Halley의 방법의 일반화 된 형태를 사용하여 해결책을 시도했지만 위의 제한으로 인해 그것이 유효하지 않다는 것을 깨달았습니다. 반복 (제곱근에 적용됨)은 다음과 같습니다.

x = x * (3*A + x*x) / (A + 3*x*x)

이 반복은 뉴턴이 가지고 있지 않은 좋은 특성을 가지고 있습니다. 그것은 입체적으로 (이차적으로가 아니라) 입체적으로 수렴하고, 위 또는 아래에서 수렴하며 (위에서 만이 아닌) 수렴되지 않은 씨앗에 민감하지 않습니다 (뉴턴의 반복이 너무 낮은 씨앗을 제공한다면, 그것은 수렴 지점을 크게 오버 슈트 한 다음 다시 내려 가야합니다).

뉴턴의 방법은 또한 (정수를 다룰 때) x가 자주 발생한다는 문제가 있습니다. A / x-x = 2 와 같이 이 경우 적절한 정수 루트보다 하나 큰 값으로 수렴합니다. 어떤 수정이 필요합니다; 할리의 방법은 그러한 수정이 필요하지 않습니다. 그러나 불행히도의 값은 3*A + x*x종종 허용 된 32 비트 정수 공간보다 클 것입니다.

다른 일반화 된 n 번째가 있습니다. 루트 알고리즘이 많이 있지만 모두 동일한 특성을 공유합니다.

x = x + x*(v - x**n)/(v*n)
x = (x*(n+1) - x**(n+1)/v)/n
x = ((n-2)*x + (4*v*x)/(v + x**n))/n
x = x*((n+2)*v + (n-2)*x**n)/(v + x**n)/n
x = ((n-2)*x + (n*x*v)/(v + (n-1)*x**n))/(n-1)
x = ((n-2)*x + x*((n*2-1)*v + x**n)/(v + (n*2-1)*x**n))/(n-1)

x = x + 2*x*(v - x**n)/(v + x**n)/n
x = x + x*31*(v - x**n)/(10*v + 21*x**n)/n
x = x + x*561*(v - x**n)/(181*v + 380*x**n)/n
x = x + x*1153*(v - x**n)/(372*v + 781*x**n)/n

등.이 중 대부분은 3 차 또는 2 차 수렴을 표시합니다. 마지막 4 개는 quartic convergence로 수렴되는 일련의 반복의 일부입니다. 그러나 실제로는 Newton의 방법을 사용하면 수백 자리를 계산할 필요가없는 한 적은 수의 작업으로 필요한 것을 얻을 수 있습니다.


꽤 좋았지 만 4294967295에서는 실패합니다. 규칙은 재미있게 작성해야합니다. 어떤 정확한 구내가 최선의 도전을하는지 논쟁 할 수 있지만, 궁극적으로 규칙이 명확하게 허용하는 것보다 명확하고 모호하지 않은 것이 훨씬 더 중요합니다.
aaaaaaaaaaaa

나는 할리가 어쨌든 가치가 있다고 생각하지 않습니다. 멀리 떨어져서 추측하면 3 배보다 조금 개선 될 것입니다. 뉴턴은 2 배보다 약간 작습니다. 정확도는 뉴턴이 두 배로 늘릴 것입니다. 따라서 하나의 할리 반복은 정확히 log(3)/log(2) ~= 1.585뉴턴 반복의 가치가 있습니다.
aaaaaaaaaaaa

@eBusiness 저는 처음에 2 개의 Halley 's를 선택했습니다. 비슷한 경우에 총 25 개의 ops를 선택했습니다 A = 0. 약 4294967295 , 그것은 감독이었습니다 : 65536² ≡ 0 으로 수정 반복이 수정되지 않습니다. 대안을 찾을 수 있는지 살펴 보겠습니다.
primo

@eBusiness가 수정되었습니다.
primo September

팩의 가장 매끄러운 제곱근, 멋진 직업, 공식 승리 배지.
aaaaaaaaaaaa

5

65 (61) 작업 (5 + 13 + 47 (43))

작업 1- 최대 (A, B)

RESULT = A + (B - A) * (A <= B)

이것이 확실한 해결책입니다. 대입이 필요하고, 비교가 필요하며, 비교에 무언가를 곱해야하며, 곱셈은 변수 중 하나 일 수 없으며 곱은 결과가 될 수 없습니다.

작업 2- 중 (A, B, C)

RESULT = A                               \
       + (B - A) * (A > B) ^ (B <= C)    \
       + (C - A) * (A > C) ^ (C <  B)

이것은 이전의 15-op 솔루션에 비해 개선 된 것으로, 세 가지 변수를 모두 조절했습니다. 이것은 두 개의 빼기를 저장했지만 다른 중심성 테스트를 도입했습니다. 테스트 자체는 간단합니다. 요소가 정확히 두 요소 중 하나 이상인 가운데에 있습니다.

작업 3 -sqrt (A)

X1     = 1024 + A / 2048
X2     = (X1  + A / X1 ) / 2
...
X10    = (X9 + A / X9 ) / 2
RESULT = X16 - (X16 * X16 > A)

11 라운드의 뉴턴 근사치. 1024의 마법 상수는 이미 WolframW에 이겼습니다 (512는 a = 2 ** 32 수렴 전에 a = 0에 대해 0으로 나누기 때문에 발생합니다). 나는 10 번의 반복에 대한 나의 주장이 완전히 깨끗하지 않다는 것을 인정하지만 여전히 괄호로 주장한다. 그러나 9가 가능한지 조사해야 할 것입니다.WolframH의 솔루션 9 번의 반복입니다.


작업 3의 첫 번째 줄이 옳지 않다고 생각합니다. 두 번째 상수는 첫 번째 상수의 4 배 여야합니다 ( "순수한"뉴턴).
Reinstate Monica

@WolframH 더 나은 초기 추측은 왜 사이클을 낭비하는지 설명 할 수 있습니다. 4 *는 어디에 있었습니까? 이것은 두 개의 반복이 하나로 롤링 된 것처럼 보입니다.
John Dvorak

(1024 + A/1024)/2 == (512 + A/2048)(와 같 X0 = 1024으며 뉴턴 시작).
Reinstate Monica

과제 1에 대한 좋은 해결책. 콜럼버스의 계란.
DavidC

@DavidCarraher 물론 올바른 해결책은 MOV RESULT, A; CMP A,B; CMOVA RESULT, B;-)입니다.
John Dvorak

5

1 : 5 연산자

RESULT = B ^ (A ^ B)*(A > B)

2:13 연산자

RESULT = B ^ (A ^ B)*(A > B) ^ (A ^ C)*(A > C) ^ (B ^ C)*(B > C)

3:27 연산자

g = 47|((0x00ffffff & A)>>10)|(A>>14)
r = (g + A/g)/3
r = (r + A/r)>>1
r = (r + A/r)>>1
r = (r + A/r)>>1
RESULT = r - (r*r-1>=A)

5

작업 3, 39 작업

편집 : 마지막 줄이 변경되었습니다. 의견을 참조하십시오.

이것은 Newthon 메소드의 구현입니다. 모든 양의 제곱과 양의 제곱에서 1을 뺀 값과 0에서 2 ^ 32-1 사이의 백만 개의 난수로 테스트했습니다. 겉으로는 재미 시작 값에 대한 짧은 (1022 + A/1022) / 2반복의 수를 최소로 (내가 생각하는) 필요로하는, 또한 수 RESULT에 대한 A=0(의 경우하지 않을 것이다 권리 1024대신 1022).

r = (511 + A/2044)
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
RESULT = r - (r > A/r)

당신과 나란히 최적화되어 나중에 상당한 시간을 게시 한 뉴턴 방법의 열등한 사본을 유지해야합니까? 좋은 생각은 똑같이 생각하고 두 가지 답변으로 나뉘어 진 해결책은 나쁘지만 # 2로 대답하지 않은 현재 상황입니다.
John Dvorak

@ JanDvorak : 물어 주셔서 감사합니다. 조금 더 짧은 방법을 답에 넣으면 괜찮습니다. 또한, 저에게 신용을 주셔서 감사합니다 :-)
Reinstate Monica

시도해 보았지만 입력 4294965360에서 4294967295까지 실패했습니다.
aaaaaaaaaaaa

@eBusiness :이 입력에 대해 어떤 결과를 얻습니까? 시험에서 65535를 얻었습니다.
Reinstate Monica

65536을 얻습니다. 규정 된 정수 형식을 사용하지 않을 수 있습니다.
aaaaaaaaaaaa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.