Chuyển đổi số thành nhị phân nhưng bạn cũng được phép sử dụng twos


20

Dựa trên ký hiệu "nhị phân, nhưng có twos" được đề cập trong video số thứ tự này , hãy viết một hàm lấy một số duy nhất làm đầu vào và xuất tất cả các biến thể của số đó trong hệ thống "nhị phân" cho phép twos.

Quy tắc

  • Mã chỉ phải là một hàm / phương thức, không phải là một chương trình đầy đủ
  • Đầu vào là một số nguyên được truyền dưới dạng tham số duy nhất cho hàm
  • Đầu ra là tất cả các biến thể hợp lệ của số đầu vào được chuyển đổi thành ký hiệu "nhị phân, nhưng có ký hiệu twos"
  • Đầu ra là giá trị trả về của hàm, nhưng có thể ở bất kỳ định dạng nào thuận tiện miễn là nó rõ ràng (ví dụ: 3 ints, 3 chuỗi, chuỗi được phân tách bằng dấu phẩy / dấu cách, mảng ints, v.v.), thứ tự là không quan trọng
  • Trong trường hợp không chắc là ngôn ngữ có chứa hàm tích hợp để đạt được kết quả, thì ngôn ngữ đó không được phép
  • Mã ngắn nhất tính bằng byte là người chiến thắng

Giải thích về đầu ra

Ví dụ: nếu bạn đã chuyển số 9, bạn có thể chuyển đổi nó thành nhị phân 1001, nhưng nếu bạn cho phép 2s ở từng vị trí, bạn cũng có thể viết nó dưới dạng 201(tức là 2*4 + 0*2 + 1*1) hoặc 121(tức là 1*4 + 2*2 + 1*1), như được hiển thị trong bảng này:

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

Vì vậy, nếu được thông qua 9, chức năng của bạn sẽ cần phải trả lại ba con số, 1001, 201121.

Format và trật tự là không thích hợp, miễn là nó rõ ràng (ví dụ [121,201,1001], "0201 0121 1001", ("1001","121","201")là kết quả hợp lệ khi đưa ra một đầu vào của 9).

Ví dụ

  • 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
Hai? Trong nhị phân? Đây có phải là máy tính lượng tử?
Matthew Roh

Câu trả lời:


10

GolfScript (25 byte) / CJam ( 19 17 byte)

GolfScript:

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

Điều này tạo ra một hàm ẩn danh (xem thảo luận meta về tính cho phép của các hàm ẩn danh ).

Bản demo trực tuyến

Một bản dịch thẳng sang CJam là (cảm ơn Martin Büttner vì đã cạo một vài nhân vật)

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

Mổ xẻ

{             # 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
}

Lý do cho hoạt động bình phương là chúng ta cần lặp lại giá trị lớn nhất có thể có biểu diễn ternary, được giải thích trong nhị phân, bằng ^. Vì 2 = 10, đại diện nhị phân "bình thường" ^là vấn đề quan trọng. Nếu chúng ta chuyển đổi nó thành ternary, chúng ta thấy rằng các trường hợp "tệ nhất" là sức mạnh của 2. Một cách tiếp cận tối ưu sẽ là đưa lý lẽ thành sức mạnh của ln 3/ln 2 ~= 1.585, nhưng bình phương thì ngắn hơn nhiều.


Tôi cá là một bản dịch của CJam sẽ nhỏ hơn rất nhiều.
Tối ưu hóa

1
@Optimizer đi trước ;-)
John Dvorak

GolfScript? người đàn ông tôi là một người mới
pythonia29033

8

Python 2 (59 byte)

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

(Rất cám ơn @grc, @xnor và @PeterTaylor đã giúp đỡ trong trò chuyện)

Đệ quy đơn giản, gọi với S(23)hoặc tương tự.

Giải trình

Ý tưởng chung là nếu nviệc mở rộng nhị phân kết thúc bằng a 1, thì mọi mở rộng giả nhị phân ("nhị phân, nhưng với twos") cũng phải kết thúc bằng a 1. Nếu không, nó có thể kết thúc bằng 0hoặc 2.

Do đó, chúng tôi xem xét bit cuối cùng n, phân chia và phân nhánh cho phù hợp.

Mổ xẻ

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

Biến:

  • n: Số chúng tôi muốn tìm mở rộng giả nhị phân của
  • B: Chuỗi giả nhị phân được xây dựng từ phải sang trái

5

Bash + coreutils, 77

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

(Đó là một TABký tự trong biểu thức grep.)

Đây là uốn cong quy tắc này một chút:

"Trong trường hợp không chắc là ngôn ngữ có chứa hàm tích hợp để đạt được kết quả, thì ngôn ngữ đó không được phép"

Nó chỉ ra rằng dcsự đảo ngược của những gì chúng ta cần được xây dựng. Ví dụ, nếu chúng ta đặt cơ sở đầu vào thành 2 và nhập một số nhị phân bằng twos, nó sẽ phân tích chính xác nó. (Tương tự nếu chế độ đầu vào là cơ sở 10, thì AF được phân tích cú pháp dưới dạng "chữ số" thập phân 10-15).

seqtạo một danh sách tất cả các số thập phân cho đến biểu diễn nhị phân chuẩn của n, được phân tích cú pháp dưới dạng thập phân. Sau đó, tất cả các số có chứa bất cứ thứ gì ngoài {0,1,2} đều được lọc ra. Sau đó dcphân tích các số còn lại dưới dạng nhị phân để xem đánh giá nào trở lại n.

Các hàm Bash chỉ có thể "trả về" các số nguyên vô hướng 0-255. Vì vậy, tôi đang tự do in danh sách lên STDOUT như là cách "trở về" của tôi. Đây là thành ngữ cho shell script.

Đầu ra:

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

4

Haskell, 82

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

đây chỉ là một giải pháp vũ phu. nó rất không hiệu quả, vì nó được cho là sẽ vượt qua 3 ^ n khả năng.


3

Jelly , 10 byte, thách thức ngôn ngữ

ṗ@3Ḷ¤Ḅ=¥Ðf

Hãy thử trực tuyến!

Một giải pháp bruteforce lên đến một số hyperbits bằng với đầu vào (định dạng này được gọi là "hyperbinary"). Như vậy, nó cực kỳ kém hiệu quả, chạy trong O (3 n ).

Giải trình

ṗ@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 byte

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);

Phá vỡ

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 byte

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);}}

Kiểm tra nó ở đây


1

k, 21 byte

Sử dụng phương pháp tương tự như câu trả lời Golfscript của Peter Taylor

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

Ví dụ:

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.