เห็นภาพอัลกอริทึมแบบยุคลิด


17

อัลกอริทึมแบบยุคลิดเป็นอัลกอริทึมที่รู้จักกันอย่างกว้างขวางสำหรับการคำนวณตัวหารสามัญที่ยิ่งใหญ่ที่สุด (GCD) ของจำนวนเต็มบวกสองตัว

อัลกอริทึม

สำหรับจุดประสงค์ของการท้าทายนี้มีการอธิบายอัลกอริทึมดังต่อไปนี้:

  1. แสดงอินพุตสองตัวเป็นบรรทัดที่อยู่ติดกันของอักขระบางตัว
    เช่นอินพุตของ3,4สามารถแสดงด้วยบรรทัดที่อยู่ติดกัน000และ0000

  2. เปลี่ยนlength(short_line)อักขระตัวแรกในบรรทัดที่ยาวขึ้นไปเป็นอีกตัวหนึ่งแล้วพูดว่า-
    มันดูเหมือน000และ---0

  3. กำจัดlength(short_line)อักขระตัวแรกในบรรทัดที่ยาวขึ้น
    ตอนนี้000,0

  4. ทำซ้ำขั้นตอนที่ 2 และ 3 จนกระทั่งทั้งสองมีความยาวเท่ากันโดยใช้สายสั้นและยาวหลังจากที่แต่ละซ้ำเช่น
    000, 0
    -00, 0
    00, 0
    -0, 0
    0,0

  5. คุณสามารถเลือกว่าจะหยุดที่นี่หรือทำซ้ำต่อและเปลี่ยนหนึ่งบรรทัดเป็นบรรทัดว่าง

แต่ละขั้นตอนเหล่านี้ควรคั่นด้วยช่วงเวลาระหว่าง 0.3s ถึง 1.5s

ความท้าทาย

เขียนโปรแกรมที่ให้ตัวเลขธรรมชาติสองตัวเป็นอินพุตสร้างเอาต์พุตที่มีลักษณะเหมือนกับเอาต์พุตของอัลกอริทึมด้านบน คุณสามารถใช้อักขระ ASCII ที่ไม่ใช่แบบไวท์สเปซอื่นที่พิมพ์ได้0และและ-ให้สอดคล้องกันและใช้อักขระเพียงสองตัว นอกจากนี้คุณยังสามารถใช้อัลกอริธึมทางเลือกที่ให้ผลลัพธ์รวมถึงเวลาได้เช่นเดียวกับที่อัลกอริทึมข้างต้นสร้างขึ้น

ตัวอย่าง

นี่คือตัวอย่างของอินพุต24,35ซึ่งเป็น coprimes ดังนั้น GCD ของพวกเขาคือ 1

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือตัวอย่างของอินพุต16,42ซึ่งมี GCD 2

ป้อนคำอธิบายรูปภาพที่นี่

กฎระเบียบ


ชี้แจง

  • บรรทัดที่แสดงตัวเลขต้องอยู่ในลำดับเดิมเช่นบรรทัดแรกและบรรทัดที่สองของ "เฟรม" ที่แสดงครั้งแรกจะต้องเป็นบรรทัดแรกและบรรทัดที่สองตามลำดับในเฟรมที่ตามมาทั้งหมด
  • หลังจากอัลกอริทึมสิ้นสุดไม่ควรเห็นเอนทิตีที่มองเห็นได้เพิ่มเติม อย่างไรก็ตามนี่ก็หมายความว่ามันจะไม่เป็นไรที่จะทำให้บรรทัดว่างถ้าคุณตรวจสอบให้แน่ใจว่า "เฟรม" สุดท้ายแสดงเป็นเวลาอย่างน้อยในเวลาเดียวกันกับที่ทำกับเฟรมอื่นทั้งหมดก่อนที่จะทำให้กรอบว่างเปล่า

@WheatWizard ข้อเสนอแนะที่ดีเกี่ยวกับมัน
busukxuan

บรรทัดต้องอยู่ในลำดับที่สัมพันธ์กันหรือไม่ หรือพวกเขาสามารถจัดลำดับใหม่ระหว่างการทำซ้ำได้หรือไม่ (การตรวจสอบเพราะหลังมีแนวโน้มที่จะกระชับมากขึ้นในภาษาส่วนใหญ่และดังนั้นฉันจำเป็นต้องรู้ว่าฉันควรใช้การเพิ่มประสิทธิภาพหรือไม่สนใจเพราะละเมิด sepc.)

@ ais523 ใช่พวกเขาทำแล้ว:-)
busukxuan

@ ais523 ใช่มันจะว่างเปล่า แต่ให้แน่ใจว่าเฟรมสุดท้ายจะได้รับเวลาการแสดงผลเดียวกันกับเฟรมอื่น ๆ
busukxuan

1
@ busukxuan โดยส่วนตัวฉันคิดว่าฉันจะอนุญาตให้เว้นวรรคต่อท้าย แต่อาจจะไม่เว้นวรรคในฐานะหนึ่งในตัวละคร "ที่มีความหมาย"
Luis Mendo

คำตอบ:


3

เยลลี่ 29 ไบต์

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

ลองออนไลน์!

นี่เป็นการกำหนดฟังก์ชั่น2Ŀ(ไม่ใช่โปรแกรมเต็มลิงค์ TIO มีส่วนท้ายที่แปลงฟังก์ชั่นเป็นโปรแกรม) ที่รับรายการของสององค์ประกอบเป็นอินพุตและแสดงผลลัพธ์บนหน้าจอ (หนึ่งในวิธี I / O ทางกฎหมายของเรา และสิ่งที่จำเป็นสำหรับความท้าทายนี้เพราะมันพูดถึงลักษณะที่ปรากฏบนหน้าจอ) นี่ถือว่าโปรแกรมทำงานในเทอร์มินัลที่เป็นไปตามมาตรฐาน ANSI (ฉันใช้gnome-terminalแต่ส่วนใหญ่จะใช้งานได้) และเทอร์มินัลนั้นว่างเปล่าในตอนแรก (ซึ่งดูเหมือนว่าเป็นค่าเริ่มต้นที่สมเหตุสมผลที่สุด) โปรดทราบว่าลองออนไลน์! ไม่ได้เป็นไปตามสมมติฐานเหล่านี้และทำให้การส่งออกจะบิดเบี้ยวมี (ฉันวิ่งโปรแกรมในท้องถิ่นเพื่อตรวจสอบว่ามันเคลื่อนไหวคาดว่าเป็น) ฉันใช้ใน1ที่ที่คำถามใช้0และ2-แทนที่

คำอธิบาย

ฟังก์ชั่นผู้ช่วย 1Ŀ (รับรายการของตัวเลขสองรายการ, เอาท์พุทพวกมันในบรรทัดแรกและบรรทัดที่สองของหน้าจอ, จากนั้นรอ 0.5 วินาที; คืนค่าอินพุต)

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

สตริง "\ x1bc" เมื่อส่งไปยังเทอร์มินัลที่เข้ากันได้กับ ANSI จะถูกตีความเป็นรหัสควบคุมเพื่อรีเซ็ตเทอร์มินัล จะเป็นการล้างหน้าจอและเลื่อนเคอร์เซอร์ไปที่มุมซ้ายบน (ซึ่งเป็นการรีเซ็ตเทอร์มินัลให้พร้อมสำหรับเอาต์พุตถัดไป)

มีการตั้งชื่อฟังก์ชันตัวช่วย 1Ŀ (Jelly autogenerates ชื่อของแบบฟอร์มนี้สำหรับฟังก์ชั่นและในความเป็นจริงไม่มีวิธีอื่นที่จะตั้งชื่อพวกเขา) แต่มันสามารถเรียกง่าย ๆ ว่าÇมาจากโปรแกรมหลัก (เพราะภาษามีชวเลขสำหรับฟังก์ชั่น )

ฟังก์ชั่นหลัก 2Ŀ (ใช้งานที่ร้องขอในคำถาม)

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 ไบต์

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 bytes

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)

ลองออนไลน์!


ใช้จำนวนเต็มสองตัวคั่นด้วยเครื่องหมายจุลภาคเป็นอินพุต


นั่นเป็นคำตอบที่ดี
ElPedro

2

Javascript (ES6), 215 194 ... 135 129 127 ไบต์

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)

การใช้

สิ่งนี้ใช้อินพุตในรูปแบบของการแกง หากต้องการใช้งานกำปั้นกำหนดฟังก์ชั่นให้กับตัวแปร (ตัวอย่างG) จากนั้นเรียกมันดังนี้:

G(5)(6)()

คำอธิบาย

ฟังก์ชันเรียกซ้ำค่อนข้างเรียกตัวเองหลังจาก 1 วินาทีตราบเท่าที่อัลกอริทึมยังไม่เสร็จ มันจะติดตามของตัวแปรที่สามcที่กำหนดว่าaและbควรจะเปลี่ยน (ถ้าcเป็น1เวลาของมันสำหรับการเปลี่ยนแปลง)

ก่อนอื่นฟังก์ชั่นจะเขียนบางสิ่งลงในคอนโซล ถ้าcเป็น0เช่นนั้นมันจะเขียนสองสตริงของศูนย์ด้วยการขึ้นบรรทัดใหม่ในระหว่าง ตั้งแต่cเริ่มต้น0เราสามารถใช้ประโยชน์จากสิ่งนี้และตั้งค่าตัวแปรทั่วโลกfและgเก็บสายอักขระบางอย่างที่เราต้องการบ่อยครั้ง (เช่น0และrepeat)

มิฉะนั้นจะสร้างสตริงที่มีเลขศูนย์และ minuses สตริงดังกล่าวทั้งหมดประกอบด้วยสองส่วน: อันดับแรกAminuses (เรียกจำนวนนี้B) จากนั้น zeroes จำนวนหนึ่ง (เรียกจำนวนนี้) จากนั้นบรรทัดใหม่จากนั้นบางส่วน (เรียกจำนวนนี้D) minuses และสุดท้ายเป็นศูนย์ (เรียกจำนวนนี้E)

หากอินพุตแรกมีขนาดเล็กกว่าอินพุตที่สองเราจำเป็นต้องลบเลขศูนย์ออกจากอินพุตที่สองดังนั้น Aเป็นศูนย์Bเท่ากับอินพุตแรกDเท่ากับอินพุตแรกและEเท่ากับอินพุตที่สองลบอินพุตแรก หากอินพุตแรกไม่เล็กกว่าอินพุตที่สองการย้อนกลับจะใช้ ( Aคืออินพุตที่สองBคืออินพุตแรกลบกับอินพุตที่สองเป็นต้น)

ด้วยค่าใหม่เหล่านี้สำหรับอินพุตและตัวแปรที่สลับcแล้วฟังก์ชันจะถูกกำหนดเวลาให้เรียกอีกครั้งในหน่วย1e3มิลลิวินาทีซึ่งเท่ากับหนึ่งวินาที

หมายเหตุ

  • ใช้alertสำหรับเอาต์พุต
  • การใช้ประโยชน์ 0และ-เช่นเดียวกับในตัวอย่าง
  • ความล่าช้าระหว่างขั้นตอนคือ 1,000 ms (1 วินาที)
  • หลังจากขั้นตอนแรกฟังก์ชั่นจะ (เนื่องจากลักษณะของ JavaScript) ส่งคืนจำนวนที่จะถูกละเว้น
  • เวอร์ชันของ TIO จะแสดงผลลัพธ์ทุกอย่างในครั้งเดียวการวางโค้ดในคอนโซลของเบราว์เซอร์จะคำนึงถึงความล่าช้า

ลองออนไลน์

ลองที่นี่!


2

Python 2 , 208 204 194 ไบต์

-4 ด้วยขอบคุณ @math_junkie สำหรับเคล็ดลับลับ ๆ ล่อๆด้วย time.sleep

-10 ด้วย @busukxuan ด้วยการชี้แจงกฎ "หน้าจอที่ชัดเจน"

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)

ลองออนไลน์!

ค่อนข้างแน่ใจว่านี่อาจจะเป็นกอล์ฟมากขึ้น มันทำให้ฉันต้องซ้ำprintและforห่วงเพื่อสร้างการหยุดชั่วคราว แต่ฉันไม่สามารถหาวิธีรอบมันในขณะนี้

หมายเหตุ

  • การหยุดชั่วคราวใช้คำใบ้จาก @math_junkie
  • ใช้งานไม่ได้กับ TIO อย่างเต็มที่เนื่องจากมันเก็บเอาท์พุทและทิ้งมันทิ้งเมื่อโปรแกรมเสร็จสิ้น ใช้งานได้ดีในคอนโซลแม้ว่า

1
คุณควรจะสามารถที่จะบันทึกไบต์โดยใช้import time, s=time.sleepและs(1)แทนที่จะห่วงสำหรับความล่าช้า
ขี้ยาคณิตศาสตร์

ขอบคุณ @math_junkie - ฉันลองใช้ชุดค่าผสมส่วนใหญ่โดยใช้time.sleepแต่พลาดชุดนั้น จะให้มันเป็นไป
ElPedro

@math_junkie - มาที่ 215 สำหรับฉัน บางทีฉันอาจจะคิดถึงบางสิ่งที่โง่ คุณสามารถโพสต์ตัวอย่างบนTry it Online ได้หรือไม่
ElPedro


1

perl, 161 149 ไบต์

... โดยไม่มีการเยื้องและการขึ้นบรรทัดใหม่:

($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
}

ใส่ไว้ในไฟล์ gcd.pl แล้วเรียกใช้ดังนี้:

perl -M5.010 gcd.pl 16 42

1
-M5.010ธง Perl เป็นฟรีเพื่อให้คุณสามารถบันทึกไม่กี่ไบต์โดยใช้มากกว่าsay print…\nนอกจากนี้ฉันค่อนข้างแน่ใจว่าเป็นชื่อที่ใช้แทนรูทีนย่อยที่ไม่ระบุชื่อของคุณแทนที่จะเก็บไว้ในตัวแปร

ขอบคุณเพื่อ ais523 สำหรับเคล็ดลับในการโกน 12 ไบต์
Kjetil S.

1

GNU Sed (พร้อมด้วย eส่วนขยาย xec), 88

คะแนนรวมถึง +3 สำหรับ -zrfsedตัวเลือกในการ

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

อินพุตถูกกำหนดเป็นสองบรรทัดใหม่ที่คั่นด้วยจำนวนเต็มแบบเอกนารีโดยใช้ตัวพิมพ์ใหญ่ Oเป็นตัวเลข

ตัวอย่างเช่นตัวอย่าง 16, 42 อาจถูกเรียกใช้เป็น:

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

ตามความคิดเห็นล่าสุดฉันไม่ได้ล้างหน้าจอระหว่างการทำซ้ำ


0

V , 47 44 ไบต์

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

ลองออนไลน์!

ส่วนหัวและส่วนท้ายของ TIO เพียงแค่ปรับเปลี่ยนgsเพื่อคัดลอกสองบรรทัดปัจจุบันไปที่ด้านล่างของหน้าจอจากนั้นลบสองบรรทัดแรกในตอนท้าย สิ่งนี้แสดงให้เห็นถึงการดำเนินการของ TIO แต่ถ้าคุณวิ่งใน V (โดยไม่มีส่วนหัวและส่วนท้าย) มันจะรอสักครู่ระหว่างการดำเนินการแต่ละครั้ง

Àé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

คุณต้องการตอนจบจริง ๆòหรือไม่?
Kritixi Lithos

มันแฮงค์ไม่ได้ จะรอจนกว่าฉันจะมีคอมพิวเตอร์ที่มี V เพื่อให้ดีบั๊กใด ๆ
nmjcman101
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.