Trình tự Collatz trên máy hai quầy


8

Chuỗi Collatz bắt đầu từ số nguyên dương n được xác định theo cách này:

  • nếu n chẵn thì chia cho 2 ( n' = n / 2)
  • nếu n là số lẻ thì nhân nó với 3 và thêm 1 ( n' = 3n + 1)

Lặp lại lần lặp ở trên cho đến khi n đạt 1.

Người ta không biết (đó là một vấn đề lớn chưa được giải quyết trong lý thuyết số) nếu chuỗi cuối cùng sẽ đạt đến số 1, bất kể số nguyên dương nào được chọn ban đầu.

Máy hai bộ đếm (2CM) là máy được trang bị hai thanh ghi có thể chứa giá trị nguyên không âm và có thể được lập trình với tập lệnh sau:

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

Chương trình 2CM chỉ đơn giản là một chuỗi các hướng dẫn, ví dụ chương trình sau chỉ đơn giản là sao chép nội dung của thanh ghi X để đăng ký Y:

cp:   DJZX end
      INCY
      JMP cp
end:  HALT

Lưu ý rằng 2CM là Turing Complete (nghĩa là nó có thể tính toán mọi hàm tính toán với một mã hóa đầu vào phù hợp, nhưng nó không liên quan ở đây). Cũng lưu ý rằng bộ hướng dẫn hơi khác một chút so với hướng dẫn trong bài viết Wikipedia.

Các thách thức

Viết chương trình 2CM ngắn nhất, tính toán và in chuỗi collatz lên đến 1 và dừng lại (thanh ghi X ban đầu chứa giá trị bắt đầu nvà thanh ghi Y ban đầu chứa 0). Lưu ý rằng độ dài của chương trình 2CM là số lượng hướng dẫn được sử dụng (không phải độ dài của văn bản).

Ví dụ: khi bắt đầu từ X = 3, nó phải in: 3 10 5 16 8 4 2 1và HALT.

Vì vậy, bạn có thể sử dụng ngôn ngữ yêu thích của mình để xây dựng trình mô phỏng / trình thông dịch 2CM, nhưng mã cuối cùng (ngắn nhất) mà bạn đặt trong câu trả lời phải bằng ngôn ngữ 2CM .


Chương trình nào chúng ta sẽ viết cho máy 2CM?
FUZxxl

Chương trình của bạn có phải kết thúc bằng HALT hay bạn cũng có thể để thực thi kết thúc?
orlp


1
@ LegionMammal978 Không quan trọng đối với kích thước mã.
FUZxxl

3
@MarzioDeBiasi Thấy tất cả những bình luận này, hãy để tôi giới thiệu hộp cát (ít nhất là cho thử thách tiếp theo của bạn). Viết các thử thách rõ ràng là khó, và ngay cả khi bạn nghĩ rằng bạn đã sắp xếp tất cả, vẫn có những câu hỏi mở cho những người dùng khác, có thể được chỉ ra trong hộp cát và giải quyết trước khi bạn đăng thử thách lên chính và mọi người bắt đầu làm việc nó
Martin Ender

Câu trả lời:


11

18 hướng dẫn

Tôi hơi thất vọng vì tôi đến muộn trong bối cảnh, vì bản chất tối giản của vấn đề và ngôn ngữ khiến ở đó (dường như) chỉ có một cách tiếp cận chung cho một câu trả lời hay. Tôi nhận được câu trả lời 19 hướng dẫn khá nhanh, nhưng tôi không cảm thấy như nó mang đủ lên bàn để đăng nó. Nhưng sau khi gãi đầu nhiều, kinh nghiệm lắp ráp z80 hacky của tôi đã xuất hiện và tôi đã tìm ra cách để lưu một hướng dẫn bằng cách sử dụng lại một khối mã cho mục đích mà nó không có ý nghĩa!

# 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

1
Tôi hy vọng thông dịch viên của tôi đã không quá tệ: P Giải pháp tốt đẹp.
orlp

1
@orlp Làm việc như một cơ duyên. Cảm ơn. :)
Runer112

1
Tôi thực sự thích giải pháp của bạn! Lạm dụng rất tốt của EvenNext :)
Nejc

4

ĐIỂM: 21

Đây là nỗ lực của tôi:

main: in Xvà nhảy tới finish(nếu X==1).

divisibility: tạo sự khác biệt nếu X%2==0hoặc X%2==1. Ngoài ra các bản sao Xđể Yvà làm cho X==0. Nhảy tới một trong hai isDivisible(nếu X%2==0) hoặc isNotDivisible(nếu X%2==1).

isDivisible: vòng lặp được sử dụng khi Y%2==0. Với mỗi lần giảm Y2, nó tăng thêm X1. Khi Y==0, nhảy tới main.

isNotDivisible: được sử dụng khi Y%2==1. Nó tăng thêm X1.

notDivLoop: vòng lặp được sử dụng khi Y%2==1. Với mỗi lần giảm Y1, nó tăng thêm X3. Khi Y==0, nhảy tới main.

finish: dừng lại

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

Được cung cấp 3 (sử dụng trình thông dịch được cung cấp bởi @orlp), kết quả được tạo ra là:

3
10 
5 
16 
8
4
2
1

4

19 hướng dẫn

Tôi đã viết thông dịch viên của riêng tôi bởi vì tôi thích như thế. Đây là giải pháp của tôi cho thông dịch viên của riêng tôi:

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

Và đây là giao diện của cú pháp tương thích với trình thông dịch khác:

# 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

Có vẻ như chúng tôi đã tìm thấy giải pháp tương tự, bạn đã sớm hơn :(
orlp

@orlp Điều đó xảy ra.
FUZxxl

3

19 hướng dẫn

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

Bạn có thể chạy nó bằng trình thông dịch của tôi .



@FUZxxl Đó là những gì tôi đã nói một giờ trước với bạn: P
orlp

Có bạn đã làm. Tôi đã viết điều này để những người khác nhận ra sự bình đẳng.
FUZxxl
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.