グリッド交差シーケンス


17

グラフ用紙を使用して、mユニットを右に移動し、nユニットを上に移動する傾斜線を引くと、n-1水平m-1グリッド線と垂直グリッド線が順番に交差します。そのシーケンスを出力するコードを書きます。

たとえば、次のようにm=5なりn=3ます。

m = 5、n = 3のグリッド線の交差

おそらく関連:ユークリッドリズムの生成フィボナッチタイリングFizzBu​​zz

入力:m,n比較的素数である2つの正の整数

出力:交差を2つの異なるトークンのシーケンスとして返すか印刷します。例えば、文字列とすることができるHV、のリストTrueFalse、または0のと1別の行に印刷されたの。トークンが常に同じであり、たとえば可変数のスペースではない限り、トークン間にセパレーターを使用できます。

テストケース:

最初のテストケースでは、空の出力が得られるか、まったく出力されません。

1 1 
1 2 H
2 1 V
1 3 HH
3 2 VHV
3 5 HVHHVH
5 3 VHVVHV
10 3 VVVHVVVHVVV
4 11 HHVHHHVHHHVHH
19 17 VHVHVHVHVHVHVHVHVVHVHVHVHVHVHVHVHV
39 100 HHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHH

形式で(m,n,output_as_list_of_0s_and_1s)

(1, 1, [])
(1, 2, [0])
(2, 1, [1])
(1, 3, [0, 0])
(3, 2, [1, 0, 1])
(3, 5, [0, 1, 0, 0, 1, 0])
(5, 3, [1, 0, 1, 1, 0, 1])
(10, 3, [1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1])
(4, 11, [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0])
(19, 17, [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1])
(39, 100, [0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0])

2
今日のPPCG:ゴルフブレゼンハムの線画アルゴリズム
スパー

追加した代替形式に基づいて、出力の一部として入力を繰り返すことができますか/する必要がありますか そうでない場合、入力と出力が同じリストの一部である理由がわかりません。
レトコラディ

@RetoKoradiいいえ、入力を含めるべきではありません。テストケースの処理を容易にするために、タプルに入れました。
xnor

答えを予測することはできますが、質問することはできません。出力トークンの1つとしてスペース文字を使用してもかまいませんか?結果として、出力に重要な先行/末尾スペースが存在する可能性があります。他のスペースはないため、すべてのスペースが重要になります。
レトコラディ

@RetoKoradiいいえ。末尾のスペースは表示されないためです。
-xnor

回答:


7

ルビー、92; ダチョウ0.7.0、38

f=->m,n{((1..m-1).map{|x|[x,1]}+(1..n-1).map{|x|[1.0*x*m/n,0]}).sort_by(&:first).map &:last}
:n;:m1-,{)o2W}%n1-,{)m n/*0pW}%+_H$_T%

両方の出力は、1と0を使用します(例:)101101


ダチョウの説明は次のとおりです。

:n;:m    store n and m as variables, keep m on the stack
1-,      from ex. 5, generate [0 1 2 3]
{...}%   map...
  )        increment, now 5 -> [1 2 3 4]
  o        push 1 (the digit 1 is special-cased as `o')
  2W       wrap the top two stack elements into an array
           we now have [[1 1] [2 1] [3 1] [4 1]]
n1-,     doing the same thing with n
{...}%   map...
  )        increment, now 3 -> [1 2]
  m n/*    multiply by slope to get the x-value for a certain y-value
  0        push 0
  pW       wrap the top two stack elements (2 is special-cased as `p')
+        concatenate the two arrays
_H$      sort-by first element (head)
_T%      map to last element (tail)

そして、Rubyコードをガイドとして使用して、全体がどのように機能するかの説明:

f = ->m,n {
    # general outline:
    # 1. collect a list of the x-coordinates of all the crossings
    # 2. sort this list by x-coordinate
    # 3. transform each coordinate into a 1 or 0 (V or H)
    # observation: there are (m-1) vertical crossings, and (n-1) horizontal
    #   crossings. the vertical ones lie on integer x-values, and the
    #   horizontal on integer y-values
    # collect array (1)
    (
        # horizontal
        (1..m-1).map{|x| [x, 1] } +
        # vertical
        (1..n-1).map{|x| [1.0 * x * m/n, 0] }  # multiply by slope to turn
                                               # y-value into x-value
    )
    .sort_by(&:first)  # sort by x-coordinate (2)
    .map &:last        # transform into 1's and 0's (3)
}

5

Python、53

これは、True / Falseリスト出力を使用します。ここでは特別なことは何もありません。

lambda m,n:[x%m<1for x in range(1,m*n)if x%m*(x%n)<1]

4

Pyth- 32 24バイト

Jmm,chk@Qddt@Qd2eMS+hJeJ

形式で標準入力を介して入力を受け取ります[m,n]。結果を0と1のリストとしてstdoutに出力します(0 = Vと1 = H)。

オンラインでテストする


説明:

J                           # J = 
 m             2            # map(lambda d: ..., range(2))
  m        t@Qd             # map(lambda k: ..., range(input[d] - 1))
   ,chk@Qdd                 # [(k + 1) / input[d], d]
                eMS+hJeJ    # print map(lambda x: x[-1], sorted(J[0] + J[-1])))

エンドをマッピングするときに構文マップ演算子を使用して、バイトを保存できます。eMはと同じmedです。
マルティセン

また、あなただけ取ることができ@"VH"ますが、印刷することが許可されているので、01の代わりに、VH
マルティセン

でインライン割り当てを使用すると、さらに1バイトを保存できますJ。ここで私は25バイトで、これまで持っているものです。pyth.herokuapp.com/...
Maltysen

@Maltysen、ありがとうございますjk。出力はリストになる可能性があるため、削除できると思います。
ティロ

インライン割り当てについての私のコメントを23で見ることができます。
マルティセン

4

IA-32マシンコード、26バイト

コードのHexdump:

60 8b 7c 24 24 8d 34 11 33 c0 2b d1 74 08 73 03
03 d6 40 aa eb f2 61 c2 04 00

私は次のCコードから始めました。

void doit(int m, int n, uint8_t* out)
{
    int t = m;
    while (true)
    {
        if (t >= n)
        {
            t -= n;
            *out++ = 1;
        }
        else
        {
            t += m;
            *out++ = 0;
        }
        if (t == n)
            break;
    }
}

出力を提供されたバッファに書き込みます。出力の長さは返されませんが、実際には必要ありません。出力の長さは常にm + n - 2次のとおりです。

int main()
{
    char out[100];
    int m = 10;
    int n = 3;
    doit(m, n, out);
    for (int i = 0; i < m + n - 2; ++i)
    {
        printf("%d ", out[i]);
    }
}

Cコードをマシンコードに変換するために、最初にいくつかの調整を行い、if/elseブランチの1つを空にし、0代わりにn次のように比較しました。

void doit(int m, int n, char* out)
{
    int t = n;
    while (true)
    {
        int r = 0;
        t -= m;
        if (t == 0)
            break;
        if (t >= 0)
        {
        }
        else
        {
            t += m + n;
            ++r;
        }
        *out++ = r;
    }
}

ここから、インラインアセンブリコードの記述は簡単です。

__declspec(naked) void __fastcall doit(int x, int y, char* out)
{
    _asm
    {
        pushad;                 // save all registers
        mov edi, [esp + 0x24];  // edi is the output address
        lea esi, [ecx + edx];   // esi is the sum m+n
    myloop:                     // edx is the working value (t)
        xor eax, eax;           // eax is the value to write (r)
        sub edx, ecx;
        jz myout;
        jae mywrite;
        add edx, esi;
        inc eax;
    mywrite:
        stosb;                  // write one value to the output
        jmp myloop;
    myout:
        popad;                  // restore all registers
        ret 4;                  // return (discarding 1 parameter on stack)
    }
}

私は好奇心が強い-なぜこのアルゴリズムが機能するのか?
xnor

@xnor非公式には、fizzbuzzシーケンスを追跡します。これtが「距離buzz」です。もし距離が少なくともnあるならfizz、行く、そうでないbuzz; 距離を更新します。それが0になるまで繰り返します
。–アナトリグ

3

Python-125バイト

非常に単純なアルゴリズムを使用して、座標をインクリメントし、ラインを越えて印刷されるタイミングを検出します。Pythへの翻訳を検討しています。

a,b=input()
i=1e-4
x=y=l=o=p=0
k=""
while len(k)<a+b-2:x+=i*a;y+=i*b;k+="V"*int(x//1-o//1)+"H"*int(y//1-p//1);o,p=x,y
print k

whileループはlines の数をチェックし、値のいずれかがint境界を超えたかどうかを減算してチェックします。

39, 100stdinのような入力を取りHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHHHVHHVHHHVHHVHHHVHHVHHHVHH、1行でstdoutのように出力します。


3

CJam、15バイト

Ll~_:*,\ff{%!^}

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

01Vおよび10H について印刷します。

説明

L          e# An empty list.
l~         e# Evaluate the input.
_:*,       e# [0, m*n).
\          e# The input (m and n).
ff{%!      e# Test if each number in [0, m*n) is divisible by m and n.
^}         e# If divisible by m, add an 10, or if divisible by n, add an 01 into
           e# the previous list. If divisible by neither, the two 0s cancel out.
           e# It's just for output. So we don't care about what the previous list
           e# is -- as long as it contains neither 0 or 1.

対角線は、対角線全体の1 / nごとに水平線と交差し、1 / mごとに垂直線と交差します。


これについての説明を追加しますか?それは非常に興味深いですが、少なくとも最初のクイックルックからは、なぜそれが機能するのか理解できません。それで遊んでみると、私はそれが相対素数である値に対してのみ機能することに気づきます(これは問題の説明で与えられます)が、私のものはすべての値に対して機能します。したがって、基礎となる数学は明らかに非常に異なります。
レトコラディ

沈み込ませた後、少なくともアルゴリズムの部分は理解できたと思います。後で出力生成ロジックを調べる必要があります。
レトコラディ

@RetoKoradi編集済み。
jimmy23013

2

TI-BASIC、32

Prompt M,N
For(X,1,MN-1
gcd(X,MN
If log(Ans
Disp N=Ans
End

簡単です。0およびのシーケンスを、1改行で区切って使用します。TI-BASICの利点は2バイトgcd(と暗黙の乗算ですが、欠点は入力に費やされる終了値と5バイトを含むForループです。



1

Haskell、78バイト

import Data.List
m#n=map snd$sort$[(x,0)|x<-[1..m-1]]++[(y*m/n,1)|y<-[1..n-1]]

使用例:

*Main> 19 # 17
[0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]
*Main> 10 # 3
[0,0,0,1,0,0,0,1,0,0,0]

仕組み:全ての垂直交点のx値のリストを作成(x,0)するためにx[1,2、...、M-1](に0垂直示す)と全ての水平交差点のx値のリスト追加(y*m/n,1)するためyには[1,2、...、n-1](1水平を示します)。ペアの2番目の要素をソートして取得します。

その日の呪い:再び私はに費やさ17バイトに持つimportためには、sortであるData.Listといない標準ライブラリに。


1

KDB(Q)、44バイト

{"HV"0=mod[asc"f"$1_til[x],1_(x*til y)%y;1]}

説明

交差ポイントのすべてのx軸値を見つけて、並べ替えます。mod 1がゼロの場合、「V」、ゼロ以外は「H」です。

テスト

q){"HV"0=mod[asc"f"$1_til[x],1_(x*til y)%y;1]}[5;3]
"VHVVHV"

1

CJam、26 24バイト

l~:N;:M{TN+Mmd:T;0a*1}*>

オンラインで試す

非常に簡単で、ブレゼンハム型アルゴリズムのほぼ直接的な実装です。

説明:

l~    Get input and convert to 2 integers.
:N;   Store away N in variable, and pop from stack.
:M    Store away M in variable.
{     Loop M times.
  T     T is the pending remainder.
  N+    Add N to pending remainder.
  M     Push M.
  md    Calculate div and mod.
  :T;   Store away mod in T, and pop it from stack
  0a    Wrap 0 in array so that it is replicated by *, not multiplied.
  *     Emit div 0s...
  1     ... and a 1.
}*      End of loop over M.
>       Pop the last 1 and 0.

01ループはエンドポイントまでずっと進んだため、最後にポップする必要がありますが、これは望みの出力の一部ではありません。私たちができることに注意してくださいではない、単にのために、それ以外の場合は1でループ回数を減らすN > Mすべて、0我々は非常に最後の解消を取得する必要がありながら、最後の反復からsが失われます0


1
あなたは使用することができる>ため;W<
jimmy23013

@ jimmy23013いいね。私1はスタックの一番上にいることを知っているので、生産的に使用することもできます。
レトコラディ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.