Urutan collatz pada mesin dua counter

8

The Collatz urut mulai dari bilangan bulat positif n didefinisikan dengan cara ini:

  • jika n bahkan maka membaginya dengan 2 ( n' = n / 2)
  • jika n ganjil maka kalikan dengan 3 dan tambahkan 1 ( n' = 3n + 1)

Ulangi iterasi di atas hingga n mencapai 1.

Tidak diketahui (ini adalah masalah utama yang belum terpecahkan dalam teori bilangan) jika urutan akhirnya akan mencapai nomor 1, terlepas dari bilangan bulat positif yang dipilih pada awalnya.

Sebuah Dua Kontra Machine (2cm) adalah mesin dilengkapi dengan dua register yang dapat menyimpan nilai integer non-negatif dan dapat diprogram dengan set instruksi berikut:

INCX    increase the value of register X
INCY    increase the value of register Y
JMP n   jump to instruction n
DJZX n  if register X is zero jump to instruction n,
        otherwise decrement its value
DJZY n  if register Y is zero jump to instruction n,
        otherwise decrement its value
HALT    halt (and accept)
PRINTX  print the content of register X

Program 2CM hanyalah urutan instruksi, misalnya program berikut hanya menyalin isi register X untuk mendaftar Y:

cp:   DJZX end
      INCY
      JMP cp
end:  HALT

Perhatikan bahwa 2CM adalah Turing Lengkap (yaitu dapat menghitung setiap fungsi yang dapat dihitung dengan pengkodean input yang sesuai, tetapi tidak relevan di sini). Perhatikan juga bahwa set instruksi sedikit berbeda dari yang ada di artikel Wikipedia.

Tantangan

Tulis program 2CM terpendek, yang menghitung dan mencetak urutan collatz hingga 1 dan berhenti (register X awalnya berisi nilai awal ndan register Y awalnya berisi 0). Perhatikan bahwa panjang program 2CM adalah jumlah instruksi yang digunakan (bukan panjang teks).

Misalnya, ketika mulai dari X = 3 harus dicetak: 3 10 5 16 8 4 2 1dan HALT.

Jadi Anda dapat menggunakan bahasa favorit Anda untuk membangun simulator / juru bahasa 2CM, tetapi kode akhir (terpendek) yang Anda masukkan dalam jawaban harus dalam bahasa 2CM .

Marzio De Biasi
sumber
Program apa yang akan kita tulis untuk mesin 2CM?
FUZxxl
Apakah program Anda harus diakhiri dengan HALT atau dapatkah Anda juga membiarkan eksekusi berjalan pada akhirnya?
orlp
1
@ LegionMammal978 Tidak masalah untuk ukuran kode.
FUZxxl
3
@MarzioDeBiasi Melihat semua komentar ini, izinkan saya merekomendasikan kotak pasir (setidaknya untuk tantangan Anda berikutnya). Menulis tantangan yang jelas itu sulit, dan bahkan jika Anda pikir Anda sudah menyelesaikan semuanya, sering ada pertanyaan terbuka untuk pengguna lain, yang dapat ditunjukkan di kotak pasir dan diatasi sebelum Anda memposting tantangan pada main dan orang-orang mulai mengerjakannya Itu.
Martin Ender

Jawaban:

11

18 instruksi

Saya agak kecewa bahwa saya datang terlambat ke tempat kejadian, karena sifat minimalis dari masalah dan bahasa yang ada (tampaknya) hanya satu pendekatan umum untuk jawaban yang baik. Saya mendapat jawaban 19 instruksi dengan cukup cepat, tetapi saya merasa tidak cukup dibawa ke meja untuk mempostingnya. Tapi setelah banyak yang menggaruk-garuk kepala, pengalaman perakitan z80 yang kadaluwarsa datang dan saya menemukan cara untuk menyimpan instruksi dengan menggunakan kembali satu blok kode untuk tujuan yang tidak dimaksudkan!

# Let N be the previous number in the Collatz sequence.

# Print N, and if N==1, halt.
# X=N, Y=0
Main:           PRINTX          # Print N.
                DJZX Done       # X=N-1 (N shouldn't be zero, so this never jumps)
                DJZX Done       # If N-1==0, halt. Otherwise, X=N-2.

# Find the parity of N and jump to the proper code to generate the next N.
# X=N-2, Y=0
FindParity:     INCY
                DJZX EvenNext   # If N%2==0, go to EvenNext with X=0, Y=N-1.
                INCY
                DJZX OddNext    # If N%2==1, go to OddNext with X=0, Y=N-1.
                JMP FindParity

# Find the next N, given that the previous N is even.
# X=0, Y=N-1
EvenNext:       INCX
                DJZY Main       # Y=Y-1 (Y should be odd, so this never jumps)
                DJZY Main       # If Y==0, go to Main with X=(Y+1)/2=N/2, Y=0.
                JMP EvenNext

# Find the next N, given that the previous N is odd.
# X=0, Y=N-1
OddNext:        INCX
                INCX
                INCX
                DJZY EvenNext   # If Y==0, go to EvenNext with X=(Y+1)*3=N*3, Y=0.
                JMP OddNext     # ^ Abuses EvenNext to do the final INCX so X=N*3+1.

# Halt.
Done:           HALT
Runer112
sumber
1
Saya harap penerjemah saya tidak terlalu buruk: P Solusi yang bagus.
orlp
1
@ orlp Bekerja seperti mantra. Terima kasih. :)
Runer112
1
Saya sangat suka solusi Anda! Penyalahgunaan EvenNext :)
Nejc
4

SCORE: 21

Ini usaha saya:

main: cetakan Xdan melompat ke finish(jika X==1).

divisibility: membuat perbedaan jika X%2==0atau X%2==1. Juga salinan Xke Ydan merek X==0. Melompat ke salah isDivisible(jika X%2==0) atau isNotDivisible(jika X%2==1).

isDivisible: loop digunakan saat Y%2==0. Untuk setiap penurunan Ysebesar 2, itu meningkat Xsebesar 1. Saat Y==0, melompat ke main.

isNotDivisible: digunakan saat Y%2==1. Ini meningkat Xsebesar 1.

notDivLoop: loop digunakan saat Y%2==1. Untuk setiap penurunan Ysebesar 1, itu meningkat Xsebesar 3. Saat Y==0, melompat ke main.

finish: berhenti

main:           PRINTX              # print X
                DJZX main           # here X is always >0 and jump never fires (it is just for decreasing)
                DJZX finish         # if initially X==1 this jumps to finish
                INCX                # establish the previous state of X
                INCX
                                    # continue with X>1

divisibility:   DJZX isDivisible    # if X%2==0, then this will fire (when jumping Y=X)
                INCY
                DJZX isNotDivisible # if X%2==1, this fires (when jumping Y=X)
                INCY
                JMP divisibility    # jump to the beginning of loop

isDivisible:    DJZY main           # this jumps to the main loop with X=X/2
                DJZY main           # this jump will never fire, because X%2==0
                INCX                # for every partition 2 of Y, increase X (making X=Y/2)
                JMP isDivisible     # jump to beginning of loop

isNotDivisible: INCX                # X=0, increase for 1
notDivLoop:     DJZY main           # in each iteration, increase X for 3 (when Y==0, X=3Y+1)
                INCX
                INCX
                INCX
                JMP notDivLoop      # jump to beginning of loop

finish:         HALT                # finally halt

Disertakan dengan 3 (menggunakan juru bahasa yang disediakan oleh @orlp), hasil yang dihasilkan adalah:

3
10 
5 
16 
8
4
2
1
Nejc
sumber
4

19 instruksi

Saya menulis juru bahasa saya sendiri karena saya suka itu. Ini solusi saya untuk juru bahasa saya sendiri:

MP
 XE
 XE
HY
 XV
 XO
 JH
WX
VYM
 JW
LYM
 X
 X
OX
 X
 X
 X
 JL
EH

Dan inilah tampilannya dengan sintaks yang kompatibel dengan juru bahasa lain:

# x = n, y = 0
main:    printx
         djzx   end
         djzx   end

# x = n - 2, y = 0 on fallthrough
half:    incy
         djzx   even
         djzx   odd
         jmp    half

evloop:  incx
# x = 0, y = n / 2  on jump to even
even:    djzy   main
         jmp    evloop

oddloop: djzy   main
         incx
         incx
# x = 0, y = (n + 1) / 2 on jump to even
odd:     incx
         incx
         incx
         incx
         jmp    oddloop

end:     halt
FUZxxl
sumber
Sepertinya kami menemukan solusi yang sama, Anda sebelumnya :(
orlp
@ Atlp Itu terjadi.
FUZxxl
3

19 instruksi

found:    PRINTX       # print input/found number
          DJZX done    # check if n == 1
          DJZX done    # after this point x == n - 2
parity:   INCY         # after this loop y == n // 2
          DJZX even
          DJZX odd
          JMP parity
odd-loop: DJZY found
          INCX
          INCX
odd:      INCX         # we enter mid-way to compute x = 6y + 4 = 3n + 1
          INCX
          INCX
          INCX
          JMP odd-loop
even:     DJZY found   # simply set x = y
          INCX
          JMP even
done:     HALT

Anda dapat menjalankannya menggunakan juru bahasa saya .

orlp
sumber
Gandakan jawaban saya .
FUZxxl
@FUZxxl Itulah yang saya katakan satu jam yang lalu kepada Anda: P
orlp
Ya, benar. Saya menulis ini sehingga orang lain menyadari kesetaraan.
FUZxxl