Konversikan 1 menjadi bilangan bulat positif dengan hanya menggunakan operasi * 3 dan / 2

11

Setiap bilangan bulat positif dapat diperoleh dengan memulai dengan 1 dan menerapkan urutan operasi, yang masing-masing dapat "dikalikan dengan 3" atau "dibagi dengan 2, membuang sisanya" .

Contoh (menulis f untuk * 3 dan g untuk / 2):

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

Tulis program dengan perilaku berikut:

Input : bilangan bulat positif, melalui stdin atau hard-coded. (Jika hard-coded, numeral input akan dikecualikan dari panjang program.)
Output : string f's dan g's sedemikian rupa <input> = 1 <string>(seperti dalam contoh). String seperti itu dalam urutan terbalik juga dapat diterima. NB: Output hanya berisi f's dan g's, atau kosong.

Pemenangnya adalah entri dengan byte terkecil dari program-plus-output ketika 41 adalah input.

res
sumber
1
Bagaimana Anda tahu ini benar?
marinus
@marinus ini diyakini benar (tetapi belum terbukti). mencari beberapa bukti.
Fabinout
@marinus, Anda dapat membuktikan bahwa itu mungkin dengan keturunan (atau setara dengan induksi yang kuat). Pemecahan kasus aktif x mod 3: jika x=3ymembangun y dan kemudian menerapkan f; jika x=3y+1membangun 2y+1dan menerapkan fkemudian g; jika x=3y+2kemudian menjadi rumit tetapi pada dasarnya bersifat rekursif.
Peter Taylor
Pada catatan terpisah, apakah output harus dalam urutan aplikasi atau apakah komposisi komposisi juga dapat diterima?
Peter Taylor
@PeterTaylor Either way tidak apa-apa.
res

Jawaban:

3

GolfScript, skor 64 (43-2 + 23)

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

(41 hardcoded, oleh karena itu -2 karakter untuk skor). Outputnya adalah

fffgffggffggffgggffgggg

yaitu 23 karakter (tanpa baris baru). Dengan konstruksi kode menjamin bahwa ia selalu mengembalikan (salah satu) representasi terpendek.

Howard
sumber
Mengutip pengguna Darren Stone dalam sunting yang disarankan pada posting ini: "Saya tidak dapat meninggalkan komentar di sini jadi saya akan meninggalkan sunting. Output ini tidak termasuk dua karakter pertama" 1 "juga tidak tercermin dalam skor. Harus menjadi perbaikan mudah dan masih merupakan solusi yang sangat singkat. Ceria! " (Saya menolak, tetapi berpikir saya harus membawa pesan itu)
Gagang Pintu
@ Doorknob Tantangannya menyatakan bahwa "1 "seharusnya tidak dimasukkan dalam output.
Howard
3

Kita menjadi kotor, teman-teman!

JAWA 210 207 199 karakter

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

non-golf:

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

output: tergantung pada kepercayaan para dewa lama, yang terpendek yang saya miliki adalah 30. Perhatikan bahwa output harus dibaca dari kanan.

234

1 ggfgfgfgfggfggfgffgfggggfgffgfggfgfggggfgffgfggfgfggfgfggfgfgggggfffgfggfgfggfgfgggffgggggfffgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggfgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggggggggggggfgfgfggggfgfgfggfffgfgfggffgfgfggfgfggggffgfgfffff

108

1 gggffgfgfggggggfggggfgffggggfgfgfgfgfgffgggfgggggfggfffggfgfffffgggffggfgfgggffggfgfgggffggggggfgfgffgfgfff

sunting 45

1 ggfgfgfgfgggfggfffgfggfgfgggggggffgffgfgfff

poin: 318 199 + 30 = 229

edit1 (2 * i + 1)% 3 == 0 -> (2 * i)% 3 == 1

Nota Bene jika Anda menggunakan Java 6 dan bukan Java 7 saat bermain golf, Anda dapat menggunakannya

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

Struktur 39 karakter alih-alih struktur standar yang panjangnya 53 karakter.

Hebat
sumber
(2*i+1)%3==0setara dengani%3==1
Howard
Ya itu. terima kasih
Fabinout
if(X){A}else{if(Y){B}else{C}}lebih panjang dari if(X){A}else if(Y){B}else{C}. Anda juga dapat mengganti ==kondisi Anda dengan <kondisi yang lebih pendek .
Peter Taylor
@PeterTaylor benar, solusi saya masih jelek. Saya tidak tahu apakah bagian acak membuat kode lebih pendek, tetapi tentu saja membuat output lebih buruk.
Fabinout
String f / g Anda dimulai dengan 'g' (yang seharusnya berarti '/ 2'), sehingga mereka akan mengkonversi 1 ke 0 alih-alih menjadi 41. Mengubah f's ke g's dan sebaliknya, juga tampaknya tidak beri 41.
res
3

Python, skor 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 karakter kode (baris baru masing-masing 1) - 2 untuk angka input hard-coded + 36 karakter output

Keluaran:

ffffffffffffffffgggggggggggggggggggg
Darren Stone
sumber
1
Jika Anda melakukannya, m=f=0Anda dapat membuat lingkaran luar while(n!=x)*(m!=x)dan menghapus istirahat. Membawa ke 95 karakter kode.
Daniel Lubarov
@Aniel: Anda, tuan, adalah pria terhormat dan cendekiawan. Terima kasih! Kiriman Anda masih aman 10 karakter di depan saya. :)
Darren Stone
1
Anda dapat lebih menghemat sedikit jika Anda mengganti semua ndengan 3**f.
Howard
1
Untuk input = 1, program Anda menghasilkan kesalahan ("nama 'g' tidak didefinisikan", karena tidak memasukkan loop sementara luar).
res
1
Anda dapat memotong karakter lain dengan menulis print'f'*f+'g'*g, yang akan memberikan skor 90-2 + ​​36 = 124.
res
3

Python, skor 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'
Daniel Lubarov
sumber
@ Darren, saya tidak yakin bagaimana menafsirkan deskripsi output, tetapi Anda mungkin benar. Saya menambahkan '1'. Terima kasih!
Daniel Lubarov
1
Anda dapat menghapus '1' (lagi!) Interpretasi asli Anda dari deskripsi output benar. Nikmati memimpin Python, lagi! :-)
Darren Stone
1
Jika Anda menggabungkan baris ke-2, ke-3, dan ke-4 ke dalam l,n,f=len(t),1,0, dan menghapus '1',dari pernyataan cetak, skor Anda akan menjadi 87-2 + 36 = 121.
res
Terima kasih teman-teman - saya menjatuhkan 1,. l,n,f=len(t),1,0memberikan jumlah karakter yang sama, bukan? (Untuk setiap variabel, sebuah =dan baris baru diganti dengan dua ,s.)
Daniel Lubarov
Jika setiap baris baru adalah satu karakter (misalnya LF gaya UNIX), maka versi satu baris dan tiga baris memiliki panjang yang sama. Jika setiap baris baru adalah dua karakter (mis. MS Windows-style CR + LF), maka versi satu-baris lebih pendek dua karakter dari versi tiga-baris. Skor 121 mengasumsikan baris baru satu karakter.
res
1

Perl, skor 89 (63 - 2 + 28)

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

Dugaan: Jika pendekatan naif yang dijelaskan dalam solusi asli saya di bawah ini pernah mencapai siklus, siklus itu akan menjadi [21, 7, 15, 5, 10, 21, ...] . Karena tidak ada contoh tandingan untuk 1 ≤ n ≤ 10 6 , ini sepertinya benar. Untuk membuktikan ini, cukuplah untuk menunjukkan bahwa ini adalah satu-satunya siklus yang bisa ada, yang mungkin saya lakukan atau tidak mungkin lakukan di kemudian hari.

Solusi di atas menghindari siklus segera, alih-alih menebak (salah), dan menghindarinya untuk kedua kalinya.

Output (28 byte):

ggfgfgfgfggfggfgfgfggfgfgfff

Perl, skor 100 (69 - 2 + 33)

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

Menggunakan pendekatan tebak-dan-periksa. String dibangun menggunakan operasi terbalik (mengubah nilai menjadi 1 , bukan sebaliknya), dan string menjadi dicerminkan sesuai, yang diizinkan oleh spesifikasi masalah.

Setiap kali non-kelipatan tiga ditemui, itu akan dikalikan dengan dua, menambahkan satu jika hasilnya kemudian kelipatan dari tiga. Ketika kelipatan tiga ditemui, itu akan dibagi tiga ... kecuali nilai ini sebelumnya telah ditemui, menunjukkan siklus, maka tebak-dan-periksa.

Output (33 byte):

ggfgfgfgfggfggfgffgfgggfggfgfgfff
primo
sumber
1

J, skor 103 (82-2 + 23)

* Catatan: Saya menamai kata kerja saya fdan g, jangan dikelirukan dengan string keluaran fdan g.

Hard-kode:

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

Fungsi umum:

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

Tidak jauh dengan beroperasi pada blok angka biner, yang merupakan perubahan paling penting sejauh pemadatan g. Mengganti nama variabel dan menghapus beberapa spasi putih untuk itu, tapi semuanya masih sama secara fungsional. (Penggunaan: g 41)

J, skor 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
)

Keluaran: ffffffffggggggggfgffggg

fmengubah daftar booleans menjadi angka, menggunakan 0s as *3dan 1s as /2(dan floor). #:i.2^imenciptakan array peringkat 2 yang berisi semua array boolean peringkat 1 panjang i.

rasionalis
sumber