정수 의 디지털 경도 를 찾으려면 이진 표현을 취하고으로 시작하거나 끝날 때까지 선행 및 후행
1
을 제거 할 수있는 횟수를 계산하십시오0
. 제거 된 총 비트 수는 디지털 경도입니다.
그것은 꽤 간결한 설명입니다. 잘 작동하는 예를 들어 보겠습니다.
이 예에서는 숫자 3167을 사용합니다. 이진수로 다음과 같습니다.
110001011111
(이진수로 변환하는 동안 선행 0을 제거해야합니다.)
로 시작하거나 끝나지 0
않으므로 1 쌍의 비트를 제거합니다.
1 1000101111 1
그리고 또 다른:
11 00010111 11
그러나 이제 시작 부분에 0이 있으므로 더 이상 1
쌍을 제거 할 수 없습니다 . 총 4 비트를 제거 했으므로 4 는 3167 의 디지털 경도입니다 .
그러나 양수 n (즉 , 이진 표현 에만 포함)에 대해 2 n -1 로 쓸 수있는 숫자의 경우 0에 도달하지 않으므로 모든 비트를 제거 할 수 있습니다. 이것은 경도가 단순히 정수의 비트 길이라는 것을 의미합니다.1
도전
음수가 아닌 정수가 주어지면 n >= 0
디지털 경도를 결정 하는 프로그램이나 함수를 작성해야합니다 .
I / O를 수행하는 전체 프로그램 또는 결과를 반환하는 함수를 제출할 수 있습니다. 귀하의 제출물은 n
귀하의 언어의 표준 정수 범위 내의 값으로 작동해야 합니다.
테스트 사례
이 중 하나라도 부정확하거나 추가 할 엣지 케이스를 제안하려면 알려주십시오.
0 -> 0
1 -> 1
8 -> 0
23 -> 2
31 -> 5
103 -> 4
127 -> 7
1877 -> 2
2015 -> 10
다음은 이러한 테스트 사례를 생성하는 데 사용 된 ungolfed Python 솔루션입니다 (버그가없는 것으로 보장되지는 않음).
def hardness(num) -> int:
binary = bin(num)[2:]
if binary.count('0') == 0:
return num.bit_length()
revbin = binary[::-1]
return min(revbin.find('0'), binary.find('0')) * 2
답변
젤리 , 11 10 바이트
BµQL××Ṛa\S
작동 원리
BµQL××Ṛa\S Main link. Argument: n
B Binary; convert n to base 2.
µ Begin a new, monadic chain. Argument: A (array of binary digits)
Q Unique; deduplicate the digits.
L Length; count the unique digits.
× Multiply each digit by the result.
×Ṛ Multiply the results by reversed A.
a\ Cumulative reduce by logical AND.
This zeroes out all elements after the first zero.
S Compute the sum of the result.
답변
파이썬 , 76 69 68 63 62 60 57 바이트
f=lambda n,k=0:n>>k&(n&n>>k>n>>k+1)and(n&n+1>0)-~f(n,k+1)
작동 원리
이것은 입력을 받아 재귀 해결책 N 및 증분 유지 K 에서 시작 – 0 – 동안 모두 LSB K (N) (비트 인덱스에서 K 오른쪽)와 MSB의 K (N) (인덱스의 비트 K 왼쪽) 설정됩니다. 완료되면 모든 n 비트가 설정 되면 k를 반환 하고 그렇지 않으면 2k를 반환합니다.
보조 변수 t를 사용 하여 람다 f 를 명명 된 함수 F 로 다시 작성해 봅시다 .
def F(n, k = 0):
t = n >> k
return t & (n & t > t >> 1) and (n & (n + 1) > 0) + 1 + F(n, k + 1)
각 호출에 F , 첫번째 비트 시프트 우리 N 개의 케이 우측 부와의 결과 저장 t를 . 이런 식으로 LSB 0 (t) = LSB k (n) 이므로 LSB k (n) 이 설정된 경우에만 t 가 홀수 입니다.
MSB k (n)의 설정 여부를 결정하는 것은 약간 까다 롭습니다. 이것이 n & t > t >> 1
달성하는 것입니다. 그것이 어떻게 작동하는지 설명하기 위해 비트 길이 8 의 정수 n = 1αβγδεζη 2 를 고려 하고 함수 호출 F (n, 3) , 즉 k = 3을 분석해 봅시다 .
우리는 비교의 진실 값 (n & t> t >> 1) = (1αβγδεζη 2 & 1αβγδ 2 > 1αβγ 2 ) 을 조사하여 MSB 3 (n) = γ 가 설정되어 있는지 확인하려고합니다 . 관련된 정수를 살펴 보자.
MSB-index 012k4567
n 1αβγδεζη
t 1αβγδ
t >> 1 1αβγ
n & t> t >> 1 인 경우에만 γ = 1 이라고 주장합니다 .
-
만약 γ = 1 다음, n은 t가 비트 길이 갖는 5 동안 t >> 1 비트 길이를 갖는 4 이므로 n은 t> t >> 1 .
이는 γ = 1이 n & t> t >> 1 임을 의미 합니다.
-
경우 n은 t> t >> 1 , 두 가지가있다 : 하나 γ = 1 또는 γ = 0 . 첫 번째 경우에는 증명할 것이 없습니다.
두 번째 경우에는 αβγδ 2 ≥ n & t> t >> 1 = 1αβγ 2 입니다.
이후 αβγδ 2 > 1αβγ 2 우리가 있어야 MSB 0 (αβγδ 2 ) MSB ≥ 0 (1αβγ 2 ) , 즉 저 α = 1 .
이런 식으로 1βγδ 2 > 11βγ 2 이므로 MSB 1 (1βγδ 2 ) ≥ MSB 1 (11βγ 2 )을 가져야 합니다. 즉, β = 1 입니다.
차례로, 이는 11γδ 2 > 111γ 2를 의미합니다 . 두 번째 경우에 γ = 0 임을 기억 하면 부등식 110δ 2 > 1110 2를 얻습니다 . 이는 MSB 2 (110δ 2 ) = 0 <1 = MSB 2 (1110 2 ) 이므로 false 입니다.
따라서 첫 번째 경우 만 가능하며 n & t> t >> 1은 γ = 1을 의미 합니다.
요약하면 LSB k (n) 과 MSB k (n) 이 모두 설정되면 t 는 홀수이고 n & t> t >> 1 은 True 가되므로 t & (n & t> t >> 1) 은 수율 1 . 그러나 LSB k (n) 또는 MSB k (n) 이 설정되지 않은 경우 (또는 둘 다인 경우), t 는 짝수이거나 n & t> t >> 1 은 False 이므로 t & (n & t> t> > 1) 은 0이 됩니다.
단일 인수로 F 를 호출 하면 k = 0이 초기화 됩니다. 앞에서 논의한 조건이 유지되는 동안, 이후의 코드 and
가 실행되는데 ,이 코드 는 (다른 것들 중에서) 증가 된 k로 F 를 재귀 적으로 호출합니다 .
일단 LSB K (N) 또는 MSB의 K (N)가 해제되면, 조건이 실패하고 F가 (N, K)를 반환 0 . 앞의 k 함수 호출 각각은 (n & (n + 1)> 0) + 1 을 F (n, k) = 0 을 더하므로 F (n) 은 ((n & (n + 1)> 0) + 1) k .
이제 n의 모든 비트 가 같으면 (즉, n 이 0 이거나 모든 비트가 설정된 경우) n + 1 은 n 과 공통 인 비트를 가지지 않으므로 n & (n + 1) = 0 이고 F (n) 은 k를 반환합니다 . 그러나 n 에 설정 및 설정 해제 비트가 모두 있으면 n & (n + 1)> 0 이고 F (n) 은 2k를 반환합니다 .
답변
MATL , 13 12 바이트
Btv`6L&)}x@q
온라인으로 사용해보십시오! 또는 모든 테스트 사례를 확인하십시오 .
설명
이 코드는 각 이진수를 반복하고 두 개의 외부 숫자를 제거 할 수있는 횟수를 계산합니다.
B % Input number (implicit). Horizontal vector of binary digits
tv % Duplicate and concatenate vertically
` % Do...while
6L&) % Flatten the array if needed (in column-major order), and split it
% into two subarrays: one with the inner entries, and another
% with the two outer entries. The latter will be used for deciding
% if the loop continues or is exited
} % Finally (execute before exiting the loop)
x % Delete last subarray of inner entries
@q % Push last iteration index minus 1
% End (implicit). The next iterarion is executed if the array at the
% top of the stack is non-empty and only contains nonzero values.
% Otherwise the loop is exited, executing the "finally" block first
% Display (implicit)
답변
파이썬, 82 바이트
나는 아직도 골프를 칠 수 있다고 생각하지만 다른 방법을 시도하는 데 시간을 보냈으며 이것이 가장 짧았습니다.
def f(n):b=bin(n)[2:];x=min(b.find('0'),b[::-1].find('0'));print(x<0)*len(b)or x*2
이것은 OP의 Python 프로그램과 유사하게 작동하지만 Sandbox에서 질문을 본 후에 그러한 프로그램이 포함되지 않은 질문을 게시하기 전에 이것을 만들었습니다.
답변
파이썬 2, 66 바이트
s=bin(input())[2:].split('0')
print len(min(s[-1],s[0]))<<1%len(s)
입력의 이진 표현을 1의 청크로 나눕니다. 첫 번째 청크와 마지막 청크 중 작은 것에서 1의 수를 세고 두 번 계산하는 단일 청크가 없으면 두 배로합니다.
답변
PowerShell , 109106 바이트
$a=[convert]::ToString($args[0],2)-split0;(((($b=$a[0].length),$a[-1].length|sort)[0]*2),$b)[$a.count-eq1]
input $args[0]
을 가져 convert
와서 .NET 호출을 toString
base 2
(즉, 이진으로)로 사용 한 다음 -split
해당 문자열을 0
s에 저장합니다 $a
. 주의 사항 : .NET 호출은 선행 0을 반환하지 않으므로 첫 번째 숫자는 항상입니다 1
.
따라서 이진 문자열은 모두 1이거나 적어도 하나의 0이 있습니다. 우리는에 의해 의사 의사 삼진을 가진 사람들을 구별합니다 $a.count-eq1
. 진 하나 이상의 제로, 왼쪽 케이스가있는 경우, 우리는 첫 번째의 길이의 최소 걸릴 [0]
문자열 1
의 마지막 [-1]
문자열을 (발견 |sort
후 [0]
). 그 중 더 짧은 것은 우리가 제거 할 수있는 가장 많은 쌍이므로, 우리는 그것을 곱합니다 2
. A의 원래 바이너리 문자열 끝이 경우주의 0
, 입력처럼 8
, 다음은 [-1].length
도있을 것입니다 0
곱한 (가 빈 문자열을 이후) 2
아직 0
.
그렇지 않으면 이진 문자열을 모두 사용하면 방금 가져 $b
옵니다 (이전에 첫 번째 [0]
문자열 의 길이 ,이 경우 이진 문자열의 전체 길이로 설정 됨 ).
두 경우 모두 해당 결과가 파이프 라인에 남아 있고 출력이 암시 적입니다.
답변
자바 스크립트 (ES6), 57 바이트
f=
n=>n.toString(2).replace(/^(1*)(.*(\1))?$/,'$1$3').length
<input oninput=o.value=1/this.value?f(+this.value):''><input id=o readonly>
이진을 취하여 1s
같은 수의 선행 및 후행과 일치 하거나 모두 실패합니다 1s
.