Hình dung thuật toán Euclide


17

Thuật toán Euclide là một thuật toán được biết đến rộng rãi để tính toán ước số chung lớn nhất (GCD) của hai số nguyên dương.

Thuật toán

Với mục đích của thử thách này, thuật toán được mô tả như dưới đây:

  1. Hiển thị hai đầu vào dưới dạng các đường liền kề của một ký tự nhất định,
    ví dụ đầu vào 3,4có thể được biểu thị bằng các đường liền kề 0000000

  2. Biến các length(short_line)ký tự đầu tiên trong dòng dài hơn thành một ký tự khác, nói -
    bây giờ nó trông giống như 000---0

  3. Loại bỏ các length(short_line)ký tự đầu tiên trong dòng dài hơn.
    tại 000,0

  4. Lặp lại bước 2 và 3 cho đến khi hai có chiều dài bằng nhau, sử dụng các đường ngắn hơn và lâu hơn sau mỗi lần lặp, ví dụ như
    000, 0
    -00, 0
    00, 0
    -0, 0
    0,0

  5. Bạn có thể chọn dừng ở đây hoặc tiếp tục lặp lại và biến một trong các dòng thành một dòng trống.

Mỗi bước này nên được phân tách bằng khoảng cách giữa 0,3 và 1,5 giây.

Các thách thức

Viết chương trình, cho hai số tự nhiên làm đầu vào, tạo ra một đầu ra trông giống hệt như đầu ra của thuật toán ở trên. Bạn có thể sử dụng các ký tự ASCII không phải khoảng trắng khác hơn 0-, nhưng nhất quán và chỉ sử dụng hai ký tự. Bạn cũng có thể sử dụng các thuật toán thay thế được cung cấp đầu ra, bao gồm cả thời gian, hoàn toàn giống với thuật toán được tạo ra ở trên.

Ví dụ

Đây là một ví dụ với đầu vào 24,35, là các phần tử sao cho GCD của chúng là 1.

nhập mô tả hình ảnh ở đây

Đây là một ví dụ với đầu vào 16,42, có GCD 2.

nhập mô tả hình ảnh ở đây

Quy tắc


Làm rõ

  • Các dòng đại diện cho các số cần giữ nguyên thứ tự ban đầu, tức là dòng thứ nhất và thứ hai của "khung" được hiển thị đầu tiên cần phải là dòng thứ nhất và thứ hai tương ứng, trong tất cả các khung tiếp theo.
  • Sau khi thuật toán kết thúc, không có thực thể hữu hình bổ sung nào xuất hiện. Tuy nhiên, điều này cũng có nghĩa là bạn có thể bỏ trống các dòng, nếu bạn chắc chắn rằng "khung" cuối cùng được hiển thị trong ít nhất cùng một khoảng thời gian như tất cả các khung khác trước khi xóa.

@WheatWizard gợi ý tuyệt vời, trên đó
busukxuan

Các dòng phải ở trong cùng một thứ tự tương đối? Hoặc chúng có thể được sắp xếp lại giữa các lần lặp? (Kiểm tra vì ngôn ngữ sau có thể ngắn gọn hơn nhiều trong hầu hết các ngôn ngữ, và do đó tôi cần biết liệu tôi nên sử dụng tối ưu hóa đó hay bỏ qua nó do vi phạm

@ ais523 Có họ làm:-)
busukxuan

@ ais523 Có, bạn có thể xóa nó đi, nhưng hãy đảm bảo khung cuối cùng được hiển thị cùng thời gian với các khung khác
busukxuan

1
@busukxuan Cá nhân tôi nghĩ rằng tôi sẽ cho phép các không gian kéo dài, nhưng có lẽ không phải là không gian như một trong những nhân vật "có ý nghĩa"
Luis Mendo

Câu trả lời:


3

Thạch , 29 byte

VY“ñc‘ỌœS.⁸
1ẋǵ+M¦ṚÇt€2ǵ⁻/¿

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

Điều này xác định một chức năng 2Ŀ(không phải là một chương trình đầy đủ; liên kết TIO chứa chân trang chuyển đổi một chức năng thành một chương trình) lấy danh sách hai thành phần làm đầu vào và hiển thị đầu ra trên màn hình (một trong những phương pháp I / O hợp pháp của chúng tôi và một điều cần thiết cho thử thách này vì nó nói về sự xuất hiện trên màn hình). Điều này giả định rằng chương trình được chạy trong một thiết bị đầu cuối tuân thủ tiêu chuẩn ANSI (tôi đã sử dụng gnome-terminalnhưng hầu hết sẽ hoạt động) và thiết bị đầu tiên ban đầu trống (có vẻ như mặc định hợp lý nhất); lưu ý rằng hãy thử trực tuyến! không không phù hợp với các giả định này, và do đó đầu ra là bị bóp méo ở đó (tôi chạy chương trình tại địa phương để xác minh rằng nó sinh động như mong đợi). Tôi sử dụng 1câu hỏi sử dụng ở đâu 0, và2thay -.

Giải trình

Hàm trợ giúp 1Ŀ (đưa ra danh sách hai danh sách các chữ số, xuất chúng trên dòng thứ nhất và thứ hai của màn hình, sau đó đợi 0,5 giây; trả về đầu vào của nó)

VY“ñc‘ỌœS.⁸
V                   Convert each list of digits to an integer
 Y                  Separate these integers by newlines
  “ñc‘              {Output that; then restart with} the list [27, 99]
      Ọ             Convert codepoints to characters (i.e. "\x1bc"
       œS.          Wait (œS) 0.5 (.) seconds
          ⁸         {Output that; then return} the initial argument

Chuỗi "\ x1bc", khi được gửi đến thiết bị đầu cuối tương thích ANSI, được hiểu là mã điều khiển để đặt lại thiết bị đầu cuối; việc này sẽ xóa màn hình và di chuyển con trỏ đến góc trên cùng bên trái (do đó đặt lại thiết bị đầu cuối sẵn sàng cho đầu ra tiếp theo).

Hàm trợ giúp được đặt tên 1Ŀ(Jelly tự tạo tên của biểu mẫu này cho các hàm và trên thực tế không có cách nào khác để đặt tên cho chúng), nhưng nó có thể được gọi đơn giản là Çtừ chương trình chính (vì ngôn ngữ có tốc ký cho các hàm có số gần đó ).

Chức năng chính 2Ŀ (thực hiện nhiệm vụ được yêu cầu trong câu hỏi)

1ẋǵ+M¦ṚÇt€2ǵ⁻/¿
1ẋ                  Convert input to unary
  Ç                 Call helper function (producing one animation frame)
   µ         µ  ¿   While
              ⁻/      the elements differ:
     M¦               Change the largest element
    +  Ṛ                by adding corresponding elements of the other element
        Ç             Call helper function (producing one animation frame)
         t€2          Delete all 2s from each side of each element
            Ç         Call helper function (producing one animation frame)

6

JavaScript (ES6), 128 124 byte

t=0
f=
(a,b,o,c,d)=>setInterval(e=>{e=[b,d,a,c];o.data=`-0
-0`.replace(/./g,c=>c.repeat(e.pop()));c|d?c=d=0:a>b?a-=c=b:b-=d=a},1e3)
<form><input id=a><input id=b><button onclick=clearTimeout(t),t=f(+a.value,+b.value,o.firstChild)>Go!</button><pre id=o>


3

Python 2 , 152 146 byte

import time
s,o='-0'
a,b=input()
while a*b:
 d,e=o*a,o*b
 if a>b:a=a-b;d=s*b+o*a
 elif b>a:b=b-a;e=s*a+o*b
 else:a=0
 print d+'\n'+e;time.sleep(1)

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


Lấy hai số nguyên được phân tách bằng dấu phẩy làm đầu vào


Đó là một câu trả lời tốt đẹp.
ElPedro

2

Javascript (ES6), 215 194 ... 135 129 127 byte

a=>b=>F=(c=0)=>alert('-'[d='repeat'](e=c&a>b&&b)+'0'[d](a-=e)+`
`+'-'[d](f=c&a<b&&a)+'0'[d](b-=f))|a-b|c&&setTimeout(F,1e3,1-c)

Sử dụng

Điều này có đầu vào trong một biến thể về cà ri. Để sử dụng nó, nắm tay gán hàm cho một biến (ví dụ G), sau đó gọi nó như thế này:

G(5)(6)()

Giải trình

Một số hàm đệ quy tự gọi sau 1 giây miễn là thuật toán chưa kết thúc. Nó theo dõi của một biến thứ ba cquyết định xem abnên được thay đổi (nếu c1, nó là thời gian cho sự thay đổi).

Đầu tiên, chức năng ghi một cái gì đó vào bàn điều khiển. Nếu c0, nó viết hai chuỗi số 0 với một dòng mới nằm giữa. Vì cđược khởi tạo 0, chúng ta có thể tận dụng lợi thế này và thiết lập các biến toàn cục fggiữ một số chuỗi chúng ta cần thường xuyên (như 0repeat).

Mặt khác, nó xây dựng một chuỗi với số 0 và dấu trừ. Tất cả các chuỗi như vậy bao gồm hai phần: đầu tiên một số (gọi số tiền này A) trừ, sau đó một số (gọi số tiền này B) số 0, sau đó là một dòng mới, sau đó một số (gọi số tiền này D) trừ và cuối cùng là một số (gọi số tiền này E) số không.

Nếu đầu vào đầu tiên nhỏ hơn đầu vào thứ hai, chúng ta cần loại bỏ các số 0 khỏi đầu vào thứ hai, Abằng 0, Bbằng với đầu vào đầu tiên, Dbằng với đầu vào thứ nhất và Ebằng đầu vào thứ hai trừ đi đầu vào thứ nhất. Nếu đầu vào thứ nhất không nhỏ hơn đầu vào thứ hai, áp dụng ngược lại ( Alà đầu vào thứ hai, Blà đầu vào đầu tiên trừ đi đầu vào thứ hai, v.v.).

Với các giá trị mới này cho đầu vào và biến được chuyển đổi c, hàm được lên lịch để được gọi lại sau 1e3mili giây, bằng một giây.

Ghi chú

  • Sử dụng alertcho đầu ra
  • Sử dụng 0-, giống như trong các ví dụ
  • Độ trễ giữa các bước là 1000 ms (1 giây)
  • Sau bước đầu tiên, hàm sẽ (do bản chất của JavaScript) trả về một số số sẽ bị bỏ qua
  • Phiên bản trên TIO xuất ra mọi thứ cùng một lúc, dán mã trong bảng điều khiển trình duyệt sẽ đưa sự chậm trễ vào tài khoản một cách chính xác

Dùng thử trực tuyến

Hãy thử nó ở đây!


2

Python 2 , 208 204 194 byte

-4 cảm ơn @math_junkie vì trò lừa bịp với time.sleep

-10 cảm ơn @busukxuan vì đã làm rõ quy tắc "xóa màn hình".

def z(a,b,y='-',w=1):
 import time;c,d,n,s='0'*a,'0'*b,'\n',time.sleep
 if w:print c+n+d;s(1)
 if b>a:d=y*a+d[a:]
 else:c=y*b+c[b:]
 print c+n+d;s(1)
 if c!=d:z(len(c),len(d),('','-')[y!='-'],0)

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

Khá chắc chắn rằng điều này có thể được chơi golf nhiều hơn. Tôi đau đớn để nhân đôi printforvòng lặp để tạo tạm dừng nhưng tôi không thể tìm ra cách làm tròn nó vào lúc này.

Ghi chú

  • Tạm dừng bây giờ sử dụng một gợi ý từ @math_junkie
  • Không hoạt động hoàn toàn trên TIO vì nó lưu trữ đầu ra và loại bỏ nó khi chương trình kết thúc. Hoạt động tốt trong giao diện điều khiển mặc dù.

1
Bạn sẽ có thể tiết kiệm một số byte sử dụng import time, s=time.sleeps(1)thay vì một vòng lặp cho sự chậm trễ
junkie toán

Cảm ơn @math_junkie - Tôi đã thử hầu hết các kết hợp bằng cách sử dụng time.sleepnhưng đã bỏ lỡ kết hợp đó. sẽ mang nó đi.
ElPedro

@math_junkie - đến với tôi là 215. Có lẽ tôi đang thiếu một cái gì đó ngu ngốc. Bạn có thể gửi một ví dụ trên Dùng thử trực tuyến ?
ElPedro


1

perl, 161 149 byte

... Không có vết lõm và dòng mới:

($a,$b)=map 0 x$_,@ARGV;
sub p{say"\n$a\n$b";sleep 1}p;
while($a ne$b){
  ($A,$B)=$b lt$a?(\$a,\$b):(\$b,\$a);
  map$$A=~s/0/-/,1..length$$B;
  p;
  $$A=~s/-//g;
  p
}

Đặt nó vào một tệp gcd.pl và chạy như thế này:

perl -M5.010 gcd.pl 16 42

1
Các -M5.010lá cờ để perl là miễn phí, vì vậy bạn có thể tiết kiệm một vài byte bằng cách sử dụng sayhơn print…\n. Ngoài ra, tôi khá chắc chắn rằng việc đặt tên cho chương trình con ẩn danh của bạn sẽ thay vì đặt tên trong một biến.

Thx đến ais523 để biết các mẹo để loại bỏ 12 byte
Kjetil S.

1

GNU Sed (có ephần mở rộng xec), 88

Điểm bao gồm +3 cho -zrfcác tùy chọn sed.

p
:
x
esleep 1
g
ta
:a
s/o+//p
t
s/^((O+)(O+)\n\2\b|(O+)\n\4\B)/\L\2\U\3\4\n\2\L\4\U/p
t

Đầu vào được đưa ra dưới dạng hai số nguyên đơn phân tách dòng mới, sử dụng chữ hoa Olàm chữ số.

Ví dụ: ví dụ 16, 42 có thể được chạy dưới dạng:

printf "%0*d\n%0*d\n" 16 0 42 0 | tr 0 O | sed -znrf euclidvis.sed

Theo các bình luận mới nhất, tôi không xóa màn hình giữa các lần lặp.


0

V , 47 44 byte

Àé0á
Àé0Hqwmmjlhmmkl@wqòHî@w
gs`mlhv0r-gsÓ-ò

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

Đầu trang và chân trang trên TIO chỉ cần sửa đổi gsđể sao chép hai dòng hiện tại xuống dưới cùng của màn hình, sau đó xóa hai dòng đầu tiên ở cuối. Điều này trực quan hóa hoạt động cho TIO, nhưng nếu bạn chạy nó trong V (không có đầu trang và chân trang), nó sẽ chỉ chờ một giây giữa mỗi thao tác.

Àé0                     " Print (Arg1) zeroes
   á                    " Newline
Àé0                     " Print (Arg2) zeroes
   H                    " Go home
    qwmmjlhmmkl@wq      " Store a recursive macro in w that finds the shorter line
                  ò     " recursively
                   Hî@w " find the longest line
gs                      " wait a second
  `mlhv0r-              " replace the zeroes of the long line with -
          gs            " wait a second
            Ó-          " delete all -
              ò         " end recursion

Bạn có thực sự cần kết thúc ò?
Kritixi Lithos

Nó treo mà không có nó, không chắc tại sao. Sẽ đợi cho đến khi tôi có một máy tính có V trên đó để gỡ lỗi bất kỳ
nmjcman101
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.