ユークリッドアルゴリズムを視覚化する


17

ユークリッドアルゴリズムは、2つの正の整数の最大公約数(GCD)を計算するための広く知られているアルゴリズムです。

アルゴリズム

この課題のために、アルゴリズムは次のように説明されています。

  1. 2つの入力を特定の文字の隣接する行として表示します。
    たとえば、の入力は3,4隣接する行で表すことができ0000000

  2. 最初に電源を入れlength(short_line)、別の文字に長い行の文字を言う-
    、今それがどのように見える000し、---0

  3. length(short_line)長い行の最初の文字を削除します。
    0000

  4. 2までの手順を繰り返し2と3は、各反復の後に短いと長い行を使用して、同じ長さを持って、例えば
    0000
    -000
    000
    -00
    00

  5. ここで停止するか、反復を続行して、行の1つを空の行にするかを選択できます。

これらの各ステップは、0.3秒から1.5秒の間隔で区切る必要があります。

チャレンジ

2つの自然数を入力として与え、上記のアルゴリズムの出力とまったく同じように見える出力を作成するプログラムを作成します。以外の空白以外の印刷可能なASCII文字を使用できますが、一貫性が0あり-、2文字のみを使用します。タイミングを含む出力が上記のアルゴリズムで生成されるものとまったく同じであれば、代替アルゴリズムを使用することもできます。

これは、24,35GCDが1であるため互いに素であるinputの例です。

ここに画像の説明を入力してください

これは、16,42GCD 2を持つinputの例です。

ここに画像の説明を入力してください

ルール


明確化

  • 番号を表す線は元の順序のままである必要があります。つまり、最初に表示される「フレーム」の最初と2番目の行は、後続のすべてのフレームでそれぞれ最初と2番目の行である必要があります。
  • アルゴリズムの終了後、追加の可視エンティティは表示されません。ただし、これは、最後の「フレーム」が他のすべてのフレームと同じ時間だけ表示されていることを確認してから空白にする前に、行を空白にしてもよいことを意味します。

その上に素晴らしい提案、@WheatWizard
busukxuan

行は同じ相対的な順序のままである必要がありますか?または、反復間で並べ替えることができますか?(後者はほとんどの言語ではるかに簡潔である可能性が高いためチェックします。したがって、sepcに違反するため、その最適化を使用するか無視するかを知る必要があります。)

@ ais523はい彼らはありません:-)
busukxuan

@ ais523はいそれは空白に大丈夫ですが、必ず最後のフレームが他のフレームと同じ表示時間を与えている作る
busukxuan

1
@busukxuan「意味のある」の文字の一つとして、個人的に私は、私は末尾のスペースをできるようになると思いますが、おそらくないスペース
ルイスMendo

回答:


3

ゼリー、29バイト

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

オンラインでお試しください!

これは、2Ŀ2つの要素のリストを入力として受け取り、画面に出力を表示する関数(完全なプログラムではなく、TIOリンクに関数をプログラムに変換するフッターが含まれます)を定義します(有効なI / Oメソッドの1つ、および画面上の外観について説明しているため、この課題に必要なものです)。これは、プログラムがANSI規格に準拠した端末で実行されていることを前提としています(私は使用しましたgnome-terminalが、ほとんどは動作します)。端末は最初は空です(最も賢明なデフォルトのようです)。オンラインで試してみてください!これらの仮定に準拠していないため、出力はそこで歪んでいます(プログラムをローカルで実行して、期待どおりにアニメーションすることを確認しました)。の代わりに使用します。1いる質問の使用0、および2-

説明

ヘルパー関数 1Ŀ(2つの数字リストのリストを指定し、画面の1行目と2行目に出力し、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Ŀ(ゼリーは、機能のために、この形式の名前を自動生成し、実際にそれらを命名する他の方法はありません)が、それは単にと呼ぶことができるÇ言語は近くの番号を持つ機能の省略形を持っているので、メインプログラム(から)。

メイン関数 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>



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秒後に自分自身を呼び出す、ある程度再帰的な関数。これは、3番目の変数のトラック続けるcかどうかを決定aし、b(あれば変更すべきcである1、それは変化の時ですが、)。

最初に、関数はコンソールに何かを書き込みます。場合c0、それは改行挟んでゼロの2つの文字列を書き込みます。以来cに初期化され0、我々は、このを活用し、グローバル変数を設定することができますfし、g多くの場合、私たちに必要ないくつかの文字列を保持すること(のように0してrepeat)。

それ以外の場合は、ゼロとマイナスの文字列を作成します。そのような文字列はすべて2つの部分で構成されています:最初は(この量を呼び出すA)マイナス、次に(この量を呼び出すB)ゼロ、次にいくつかの(この量を呼び出すD)マイナス、最後に(この量を呼び出すE)ゼロ。

最初の入力が2番目の入力よりも小さい場合、2番目の入力からゼロを削除する必要Aがあります。ゼロBは1番目の入力にD等しく、最初の入力にE等しく、2番目の入力から最初の入力を引いた値に等しくなります。最初の入力が2番目の入力よりも小さくない場合、逆が適用されます(A2番目の入力、B最初の入力から2番目の入力を引いたものなど)。

入力とスイッチ変数のこれらの新しい値によりc、関数は1e3ミリ秒単位で再び呼び出されるようにスケジュールされます。これは1秒に相当します。

ノート

  • alert出力に使用
  • 0およびの使用-例と同様
  • ステップ間の遅延は1000 ms(1秒)です
  • 最初のステップの後、関数は(JavaScriptの性質により)無視される数値を返します
  • TIOのバージョンはすべてを一度に出力します。ブラウザコンソールにコードを貼り付けると、遅延が適切に考慮されます

オンラインで試す

ここで試してみてください!


2

Python 2 208の 204 194バイト

-4で@math_junkieに感謝します time.sleep

「クリアスクリーン」ルールを明確にしてくれた@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)

オンラインでお試しください!

これはもっとゴルフできると確信しています。これは、複製するために私に痛みprintfor一時停止を作成するためのループを、私は現時点ではそれ丸い方法を見つけることができません。

ノート

  • 一時停止は@math_junkieからのヒントを使用するようになりました
  • TIOは出力を保存し、プログラムの終了時にダンプするため、TIOで完全には機能しません。ただし、コンソールでは正常に動作します。

1
あなたは、使用していくつかのバイトを保存することができるはずimport times=time.sleeps(1)代わりに遅延のためのループの
数学中毒

ありがとう@math_junkie-私はほとんどの組み合わせを使って試しましたtime.sleepが、それを逃しました。それを試してみます。
エルペドロ

@math_junkie-215になりました。たぶん私は何か愚かなことを見逃しています。Try it Onlineに例を投稿できますか?
エルペドロ


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.010perl のフラグは無料なので、sayover を使用して数バイト節約できますprint…\n。さらに、変数に格納するのではなく、匿名サブルーチンに名前を付けるのは簡単だと確信しています。

12バイトを削減するためのヒントについては、ais523への送信
Kjetil S.

1

GNU Sed(と e xec拡張付き)、88

スコアの-zrfオプションには+3が含まれます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

入力は、大文字Oを数字として使用して、2つの改行で区切られた単項整数として与えられます。

たとえば、16、42の例は次のように実行できます。

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

最新のコメントによると、繰り返しの間に画面をクリアするわけではありません。


0

V47 44バイト

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

オンラインでお試しください!

TIOのヘッダーとフッターはgs、現在の2行を画面の下部にコピーするように変更し、最後の最初の2行を削除します。これにより、TIOの操作が視覚化されますが、Vで(ヘッダーとフッターなしで)実行した場合、各操作の間に1秒だけ待機します。

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