숫자를 이진수로 변환하지만… 둘을 사용할 수 있습니다


20

이 numberphile 비디오에 언급 된 "이진수이지만 둘을 갖는"표기법에 따라 단일 숫자를 입력으로 사용하고 두 숫자가 허용되는 "이진"시스템에서 해당 숫자의 모든 변형을 출력하는 함수를 작성하십시오 .

규칙

  • 코드는 완전한 프로그램이 아니라 함수 / 방법이어야합니다.
  • 입력은 함수에 유일한 매개 변수로 전달 된 정수입니다.
  • 출력은 입력 번호의 모든 유효한 변형이 "이진수로 변환되지만 2"표기법으로 변환됩니다.
  • 출력은 함수의 반환 값이지만 명백한 한 (예 : 3 개의 정수, 3 개의 문자열, 쉼표 / ​​공백으로 구분 된 문자열, 정수의 배열 등), 순서는 중요하지 않은 한 편리한 형식 일 수 있습니다.
  • 결과에 도달하기 위해 언어에 내장 함수가 포함되어있는 경우에는 허용되지 않습니다.
  • 가장 짧은 코드는 바이트입니다

출력 설명

당신이 수를 통과하는 경우 예를함으로써 9, 당신은 바이너리로 변환 할 수 있습니다 1001,하지만 당신이 허용하는 경우 2각 위치에들, 당신은 또한으로 쓸 수 있습니다 201(예 2*4 + 0*2 + 1*1) 또는 121(예 1*4 + 2*2 + 1*1)이 표에서와 같이 :

+----+----+----+----+
| 8s | 4s | 2s | 1s |
+----+----+----+----+
|  1 |  0 |  0 |  1 |
|  0 |  2 |  0 |  1 |
|  0 |  1 |  2 |  1 |
+----+----+----+----+

따라서 전달 9되면 함수는 세 개의 숫자 1001, 201및 을 반환해야합니다 121.

형식과 순서는 오랫동안이 명백으로 (즉, 관련이없는 [121,201,1001], "0201 0121 1001", ("1001","121","201")의 입력을 제공 할 때 유효한 결과가있다 9).

  • 2 => 10, 2
  • 9 => 1001, 201, 121
  • 10 => 1010, 210, 202, 1002, 122
  • 23 => 2111, 10111
  • 37 => 100101, 20101, 100021, 20021, 12101, 12021, 11221


1
두? 바이너리로? 이 양자 컴퓨팅입니까?
Matthew Roh

답변:


10

GolfScript (25 바이트) / CJam ( 19 17 바이트)

GolfScript :

{:^.*,{3base}%{2base^=},}

이것은 익명 함수를 생성합니다 (익명 함수 허용에 대한 메타 토론 참조 ).

온라인 데모

CJam으로의 직접적인 번역은 다음과 같습니다 ( 마르틴 부트 너 덕분에 두 캐릭터를 면도했습니다)

{:X_*,3fb{2bX=},}

해부

{             # Function boilerplate
  :^          # Store parameter as variable ^
  .*          # Square parameter - see detailed explanation below
  ,{3base}%   # Produce an array of 0 to ^*^-1 in ternary
  {2base^=},  # Filter to those which evaluate to ^ in binary
}

제곱 연산의 이유는 이진수로 해석되는 삼항 표현이 같은 최대 값을 반복해야하기 때문 ^입니다. 이므로 2 = 10"정상적인"이진 표현 ^이 중요합니다. 이것을 삼항으로 변환하면 "최악의"사례는 2의 거듭 제곱임을 알 수 있습니다. 최적의 접근 방식은의 거듭 제곱에 대한 논쟁을 취하는 ln 3/ln 2 ~= 1.585것이지만, 제곱은 훨씬 짧습니다.


나는 CJam 번역이 훨씬 작을 것이라고 확신합니다.
Optimizer

1
;-) 진행 @Optimizer
존 드보락에게

GolfScript? 남자 나는 그런 멍청한 사람입니다
pythonian29033

8

파이썬 2 (59 바이트)

S=lambda n,B="":[B][n:]or~n%2*S(n/2-1,"2"+B)+S(n/2,`n&1`+B)

(채팅에 도움을 주신 @grc, @xnor 및 @PeterTaylor에게 감사드립니다)

간단한 재귀, 호출 S(23)또는 유사.

설명

일반적으로 n이진 확장이로 끝나는 1경우 의사 이진 ( "이진이지만 두 개") 확장도로 끝나야합니다 1. 그렇지 않으면 0또는로 끝날 수 2있습니다.

따라서 우리는의 마지막 비트를보고 n그에 따라 나누고 분기합니다.

해부

S=lambda n,B="":           # Lambda expression
[B][n:]or                  # Short circuit, return [B] if n==0 else what follows
~n%2*                      # Keep next list result if n is even else turn into []
S(n/2-1,"2"+B)             # Add a "2" to B, recurse
+
S(n/2,`n&1`+B)             # Add "0" or "1" to B depending on n's last bit, recurse

변수:

  • n: 의사 이진 확장을 찾고자하는 수
  • B: 오른쪽에서 왼쪽으로 생성되는 의사 이진 문자열

5

배쉬 + 코어 유틸리티, 77

f()(seq `dc -e2o$1p`|sed '/[3-9]/d;s/.*/&n9P2i&pAi/'|dc|grep -Po ".*(?= $1)")

(그것은 TABgrep 표현 의 문자입니다.)

이것은이 규칙을 약간 굽히고 있습니다.

"언어가 결과에 도달하기 위해 언어에 내장 함수가 포함되어있는 경우 허용되지 않습니다."

그것은 그 판명 dc반대로 우리가 내장 필요가 무엇인지를. 예를 들어 우리는 2 입력의 보수와 진수를 입력 기준을 설정 한 경우, 올바르게 구문 분석됩니다. 입력 모드가 10 진법 인 경우와 유사하게 AF는 10 진수 "숫자"10-15로 해석됩니다.

seq표준 이진 표현 n까지의 모든 십진수 목록을 십진수로 구문 분석합니다. 그런 다음 {0,1,2} 이외의 것을 포함하는 모든 숫자가 필터링됩니다. 그런 다음 dc나머지 숫자를 이진수로 구문 분석하여 n으로 다시 평가되는 것을 확인하십시오.

Bash 함수는 스칼라 정수 0-255 만 "반환"할 수 있습니다. 그래서 나는 "돌아가는"방법으로 목록을 STDOUT에 자유롭게 인쇄하고 있습니다. 이것은 쉘 스크립트에 관용적입니다.

산출:

$ f 2
2   
10  
$ f 9
121 
201 
1001    
$

4

하스켈, 82

t n=[dropWhile(==0)s|s<-mapM(\_->[0..2])[0..n],n==sum[2^(n-i)*v|(i,v)<-zip[0..]s]]

이것은 단지 무차별 솔루션입니다. 3 ^ n 가능성을 통해 위기가 발생할 것으로 예상되므로 매우 비효율적입니다.


3

젤리 , 10 바이트, 언어 날짜 도전

ṗ@3Ḷ¤Ḅ=¥Ðf

온라인으로 사용해보십시오!

입력과 동일한 수의 하이퍼 비트까지 무차별 솔루션 (이 형식은 "하이퍼 바이너리"라고 함). 따라서 O (3 n ) 에서 실행되는 것은 매우 비효율적 입니다.

설명

ṗ@3Ḷ¤Ḅ=¥Ðf
ṗ@            Construct all lists with the given length, and elements taken from
  3Ḷ¤         the list [0,1,2]
        Ðf    then take only those elements which
     Ḅ=¥      when interpreted as binary, equal {the original number}

2

PHP, 138 바이트

function p($v,$i=0,$r=""){global$a;if($v==0)$a[]=$r?:0;elseif($v>0)for(;$l<3;)p($v-2**$i*$l,$i+1,+$l++.$r);}p($argv[1]);echo join(",",$a);

고장

function p($v,$i=0,$r=""){
    global$a;
    if($v==0)$a[]=$r?:0;  # fill result array
    elseif($v>0) # make permutations
        for(;$l<3;)
            p($v-2**$i*$l,$i+1,+$l++.$r); #recursive
}
p($argv[1]);
echo join(",",$a); # Output

1

C ++, 159 바이트

void c(int x,string r){int i,t=0,s=r.size();if(s<8){if(r[0]>48){for(i=0;i<s;i++)t+=(r[s-i-1]-48)*1<<i;if(t==x)cout<<r<<" ";}for(char n=48;n<51;n++)c(x,r+n);}}

여기에서 테스트


1

k, 21 바이트

Peter Taylor의 Golfscript 답변과 동일한 방법을 사용합니다

{X@&x=2/:'X:3\:'!x*x}

예 :

k) {X@&x=2/:'X:3\:'!x*x}9
(1 2 1;2 0 1;1 0 0 1)
k) {X@&x=2/:'X:3\:'!x*x}10
(1 2 2;2 0 2;2 1 0;1 0 0 2;1 0 1 0)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.