Chuyển đổi 1 thành bất kỳ số nguyên dương nào chỉ bằng các thao tác * 3 và / 2


11

Bất kỳ số nguyên dương nào cũng có thể thu được bằng cách bắt đầu bằng 1 và áp dụng một chuỗi các thao tác, mỗi số này là "nhân với 3" hoặc "chia cho 2, loại bỏ phần còn lại" .

Ví dụ (viết f cho * 3 và g cho / 2):

4 = 1 *3 *3 /2 = 1 ffg
6 = 1 ffggf = 1 fffgg
21 = 1 fffgfgfgggf

Viết chương trình với hành vi sau:

Đầu vào : bất kỳ số nguyên dương nào, thông qua stdin hoặc mã hóa cứng. (Nếu được mã hóa cứng, số đầu vào sẽ được loại trừ khỏi độ dài chương trình.)
Đầu ra : một chuỗi f và g sao cho <input> = 1 <string>(như trong ví dụ). Một chuỗi như vậy theo thứ tự ngược lại cũng được chấp nhận. NB: Đầu ra chỉ chứa f và g, hoặc trống.

Người chiến thắng là mục có ít byte đầu ra của chương trình cộng với đầu ra khi 41 là đầu vào.


1
Làm thế nào để bạn biết điều này là đúng?
bến tàu

@marinus điều này được cho là đúng (nhưng chưa được chứng minh). tìm kiếm một số bằng chứng
Fabinout

@marinus, bạn có thể chứng minh rằng có thể bằng cách hạ xuống (hoặc tương đương bằng cảm ứng mạnh). Phân chia trường hợp trên x mod 3: nếu x=3yxây dựng y và sau đó áp dụng f; nếu x=3y+1xây dựng 2y+1và áp dụng fsau đó g; nếu x=3y+2sau đó nó trở nên phức tạp nhưng về cơ bản là đệ quy.
Peter Taylor

Trên một lưu ý riêng, đầu ra phải theo thứ tự ứng dụng hay thứ tự thành phần cũng được chấp nhận?
Peter Taylor

@PeterTaylor Cả hai cách đều ổn.
res

Câu trả lời:


3

GolfScript, điểm 64 (43-2 + 23)

0{)1.$2base:s{{3*}{2/}if}/41=!}do;s{103^}%+

(41 là mã hóa cứng, do đó -2 ký tự cho điểm). Đầu ra là

fffgffggffggffgggffgggg

đó là 23 ký tự (không có dòng mới). Bằng cách xây dựng mã đảm bảo rằng nó luôn trả về (một trong) các biểu diễn ngắn nhất.


Trích dẫn người dùng Darren Stone trong một chỉnh sửa được đề xuất trên bài đăng này: "Tôi không thể để lại nhận xét ở đây vì vậy tôi sẽ để lại một chỉnh sửa. Đầu ra này không bao gồm hai ký tự đầu tiên" 1 "cũng không phải là những ký tự được phản ánh trong điểm số. sửa chữa dễ dàng và vẫn là một giải pháp cực kỳ ngắn. Chúc mừng! " (Tôi đã từ chối, nhưng nghĩ rằng tôi nên mang theo tin nhắn)
Doorknob

@Doorknob Thách thức nói rằng "1 "không nên đưa vào đầu ra.
Howard

3

Các bạn ạ!

JAVA 210 207 199 ký tự

public class C{public static void main(String[] a){int i=41;String s="";while(i>1){if(i%3<1){s+="f";i/=3;}else if(i%3<2){s+="g";i+=i+1;}else{s+="g";i+=i+(Math.random()+0.5);}}System.out.println(s);}}

không chơi gôn:

public class C {

    public static void main(String[] a) {

        int i = 41;
        String s = "";
        while (i > 1) {
            if (i % 3 == 0) {
                s += "f";
                i /= 3;
            } else {
                if (i % 3 == 1) {
                    s += "g";
                    i += i + 1;
                } else {
                    s += "g";
                    i += i + (Math.random() + 0.5);
                }
            }
        }
        System.out.println(s);
    }
}

đầu ra: tùy thuộc vào đức tin của các vị thần cũ, thời gian ngắn nhất tôi có là 30. Lưu ý rằng đầu ra phải được đọc từ bên phải.

234

1 ggfgfgfgfggfggfgffgfggggfgffgfggfgfggggfgffgfggfgfggfgfggfgfgggggfffgfggfgfggfgfgggffgggggfffgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggfgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggggggggggggfgfgfggggfgfgfggfffgfgfggffgfgfggfgfggggffgfgfffff

108

1 gggffgfgfggggggfggggfgffggggfgfgfgfgfgffgggfgggggfggfffggfgfffffgggffggfgfgggffggfgfgggffggggggfgfgffgfgfff

chỉnh sửa 45

1 ggfgfgfgfgggfggfffgfggfgfgggggggffgffgfgfff

điểm: 318 199 + 30 = 229

chỉnh sửa1 (2 * i + 1)% 3 == 0 -> (2 * i)% 3 == 1

Nota Bene nếu bạn sử dụng Java 6 chứ không phải Java 7 khi chơi gôn, bạn có thể sử dụng

public class NoMain {
    static {
        //some code
        System.exit(1);
    }
}

Cấu trúc 39 ký tự thay vì cấu trúc tiêu chuẩn dài 53 ký tự.


(2*i+1)%3==0tương đương vớii%3==1
Howard

Vâng, đúng vậy. cảm ơn
Fabinout

if(X){A}else{if(Y){B}else{C}}dài hơn if(X){A}else if(Y){B}else{C}. Ngoài ra, bạn có thể thay thế ==điều kiện của bạn với <điều kiện ngắn hơn .
Peter Taylor

@PeterTaylor đúng, giải pháp của tôi vẫn xấu. Tôi không biết nếu phần ngẫu nhiên làm cho mã ngắn hơn, nhưng nó đảm bảo làm cho crappier đầu ra.
Fabinout

Chuỗi f / g của bạn bắt đầu bằng 'g' (được cho là viết tắt của '/ 2'), vì vậy chúng sẽ chuyển đổi 1 thành 0 thay vì thành 41. Thay đổi f thành g và ngược lại, dường như cũng không cho 41.
res

3

Con trăn, điểm số 124 (90-2 + ​​36)

x=41;m=f=g=0
while(3**f!=x)*(m!=x):
 f+=1;m=3**f;g=0
 while m>x:m/=2;g+=1
print'f'*f+'g'*g

90 ký tự mã (dòng mới là 1 ký tự) - 2 cho số đầu vào được mã hóa cứng + 36 ký tự đầu ra

Đầu ra:

ffffffffffffffffgggggggggggggggggggg

1
Nếu bạn làm m=f=0bạn có thể thực hiện các vòng lặp bên ngoài while(n!=x)*(m!=x)và loại bỏ các phá vỡ. Mang đến 95 ký tự mã.
Daniel Lubarov

@Daniel: Bạn, thưa ngài, là một quý ông và một học giả. Cảm ơn! Trình của bạn vẫn an toàn 10 ký tự trước mặt tôi. :)
Darren Stone

1
Bạn có thể tiết kiệm thêm một chút nếu bạn thay thế tất cả nbằng 3**f.
Howard

1
Đối với đầu vào = 1, chương trình của bạn tạo ra lỗi ("tên 'g' không được xác định", do không nhập vòng lặp while bên ngoài).
res

1
Bạn có thể cắt ra một nhân vật khác bằng cách viết print'f'*f+'g'*g, trong đó sẽ đưa ra một số điểm 90-2 + 36 = 124.
res

3

Python, điểm 121 (87 - 2 + 36)

t=bin(41)
l,n,f=len(t),1,0
while bin(n)[:l]!=t:f+=1;n*=3
print(len(bin(n))-l)*'g'+f*'f'

@Darren, tôi không chắc cách diễn giải mô tả đầu ra, nhưng có lẽ bạn đã đúng. Tôi đã thêm '1'. Cảm ơn!
Daniel Lubarov

1
Bạn có thể bỏ '1' (một lần nữa!) Diễn giải ban đầu của bạn về mô tả đầu ra là chính xác. Hãy tận hưởng sự dẫn dắt của Python, một lần nữa! :-)
Darren Stone

1
Nếu bạn kết hợp các dòng thứ 2, 3 và 4 của mình vào l,n,f=len(t),1,0và xóa '1',câu lệnh in, điểm của bạn sẽ là 87-2 + 36 = 121.
res

Thanks guys - Anh đã đánh rơi những 1,. l,n,f=len(t),1,0cho cùng một số ký tự, phải không? (Đối với mỗi biến, một =và một dòng mới được thay thế bằng hai ,s.)
Daniel Lubarov

Nếu mỗi dòng mới là một ký tự (ví dụ: kiểu UNIX), thì phiên bản một dòng và ba dòng có cùng độ dài. Nếu mỗi dòng mới là hai ký tự (ví dụ: CR + LF kiểu MS Windows), thì phiên bản một dòng ngắn hơn hai ký tự so với phiên bản ba dòng. Điểm số 121 giả định các dòng mới một ký tự.
res

1

Perl, điểm 89 (63 - 2 + 28)

$_=41;$_=${$g=$_%3||$_==21?g:f}?$_*2+$_%3%2:$_/3while$_>print$g

Phỏng đoán: Nếu cách tiếp cận ngây thơ được mô tả trong giải pháp ban đầu của tôi dưới đây từng đạt đến một chu kỳ, chu kỳ đó sẽ là [21, 7, 15, 5, 10, 21, ...] . Vì không có ví dụ ngược lại cho 1 ≤ n ≤ 10 6 , điều này có vẻ đúng. Để chứng minh điều này, sẽ đủ cho thấy rằng đây là chu kỳ duy nhất có thể tồn tại, điều mà tôi có thể hoặc không thể làm vào thời điểm muộn hơn.

Giải pháp trên tránh được chu kỳ ngay lập tức, thay vì đoán (sai) và tránh lần thứ hai đi qua.

Đầu ra (28 byte):

ggfgfgfgfggfggfgfgfggfgfgfff

Perl, điểm 100 (69 - 2 + 33)

$_=41;1while$_>print$s{$_=$$g?$_*2+$_%3%2:$_/3}=$g=$_%3||$s{$_/3}?g:f

Sử dụng một phương pháp đoán và kiểm tra. Chuỗi được xây dựng bằng cách sử dụng các phép toán nghịch đảo (chuyển đổi giá trị thành 1 , thay vì ngược lại) và chuỗi được nhân đôi theo đó, được đặc tả vấn đề cho phép.

Bất cứ khi nào không có bội số của ba, nó sẽ được nhân với hai, thêm một nếu kết quả sẽ là bội số của ba. Khi gặp bội số của ba, nó sẽ được chia cho ba ... trừ khi giá trị này đã gặp trước đó, biểu thị một chu kỳ, do đó đoán và kiểm tra.

Đầu ra (33 byte):

ggfgfgfgfggfggfgffgfgggfggfgfgfff

1

J, điểm 103 (82-2 + 23)

* Lưu ý: Tôi đặt tên cho động từ của mình fg, không bị nhầm lẫn với chuỗi đầu ra fg.

Mã hóa cứng:

f=:3 :'s=.1 for_a.y do.s=.((<.&-:)`(*&3)@.a)s end.'
'gf'{~#:(>:^:(41&~:@f@#:)^:_)1

Chức năng chung:

f=:3 :'s=.1 for_a.y do.s=.((<.&-:)`(*&3)@.a)s end.'
g=:3 :'''gf''{~#:(>:^:(y&~:@f@#:)^:_)1'

Đã bỏ đi với việc vận hành trên các khối số nhị phân, đó là thay đổi quan trọng nhất cho đến khi nén g. Đổi tên các biến và loại bỏ một số khoảng trắng cho cái quái của nó, nhưng mọi thứ vẫn hoạt động như nhau. (Cách sử dụng g 41:)

J, điểm 197 (174 + 23)

f =: 3 : 0
acc =. 1
for_a. y do. acc =. ((*&3)`(<.&-:)@.a) acc end.
)

g =: 3 : 0
f2 =: f"1 f.
l =. 0$0
i =. 1
while. 0=$(l=.(#~(y&=@:f2))#:i.2^i) do. i=.>:i end.
'fg'{~{.l
)

Đầu ra: ffffffffggggggggfgffggg

fchuyển đổi một danh sách các booleans thành số, sử dụng 0s *3và 1s là /2(và floor). #:i.2^itạo một mảng hạng 2 chứa tất cả các mảng boolean xếp hạng 1 có độ dài i.

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.