オルゴールを作る


23

あなたの仕事は、文字列(音楽)を入力(関数またはプログラム)として受け取り、音楽をオルゴールのように印刷(または返す)することです。

ABCDEFG.()入力として文字を受け取るだけで、入力が空になることはありません。必要に応じて、手紙を小文字で受け取ることもあります。

これは長さ3の空のオルゴールです。

.......
.......
.......

ご覧のとおり、行の長さは7文字で、オルゴールの長さは3なので、3行です。.オルゴールは空なので、ここにはのみがあります。音楽を入れましょう!

まず、オルゴールを作成します。この例では、入力はになりますCDAG.DAG

の長さCDAG.DAGは8なので、長さ8のオルゴールが必要です。

.......
.......
.......
.......
.......
.......
.......
.......

次に、入力を一度に1文字ずつ読み取り、Oそれぞれの位置に配置します。

最初の文字はでC、各音符の位置はこれと同等です(わかりやすくするためにスペースを追加しました)。

 A B C D E F G
 . . . . . . .
 . . . . . . .
 (and so on)

入力文字がの場合、.空の行を出力するだけです.......

だから、にC沿って3番目の文字になります。上部のオルゴールに入れましょう:

..O....
.......
.......
.......
.......
.......
.......
.......

他のすべての文字についてこのプロセスを繰り返します(括弧内のテキストは、単にメモを表示するためのものであり、出力しないでください)。

..O.... (C)
...O... (D)
O...... (A)
......O (G)
....... (.)
...O... (D)
O...... (A)
......O (G)

オルゴールのしくみのため、出力でO.および以外の文字(<insert newline here>スペースなど)を使用すると、正しい音楽が再生されません!

これは和音です:

(ACE)

このコードは、音符を再生するために私たちに指示されACかつE同時に。.和音に一時停止()はありません。

これはどのように書かれるかです:

O.O.O...

そして、これは音楽でどのように見えるかです: B(ACE)D

和音で和音を受け取ることはありません。つまり、これは無効です。 (AB(CD)EF)またはthis A(B()):、そして和音は空になりません、つまりこれは無効になります:A()B

無効な入力を受け取ることはありません。

例:

B(ACE)D

.O.....
O.O.O..
...O...

B

.O.....

GGABC

......O
......O
O......
.O.....
..O....

...

.......
.......
.......

A..F.C(DA).

O......
.......
.......
.....O.
.......
..O....
O..O...
.......

.(ABCDEF)

.......
OOOOOO.

出力の末尾/先頭の空白は許可されます。

これは、最短のコードが勝ちです!


音楽文字列に()2回含めることができます(例AB(CD)E(FG):)??
Mr Xcoder

@ Mr.Xcoderはい、できます。
Okx

出力は文字のリスト/配列になりますか?
ロッド

必ず、PPCG規格どおり@Rod
Okx

同じ和音で同じ音符を2つ受け取らないことが保証されていますか?
ビジネス猫

回答:


0

ピップ、29バイト

28バイトのコード、+ 1 -lフラグ。

'.X7RA_'OMz@?a@`\(\w+.|.`@XL

コマンドライン引数として小文字の入力を受け取ります。 オンラインでお試しください!

説明

                              a is 1st cmdline arg; XL is `[a-z]`; z is lowercase alphabet
             a@`\(\w+.|.`     List of all matches in a of this regex:
                               Either a ( followed by letters followed by another
                               character (i.e. the closing paren), or any one character
                         @XL  For each of those matches, a list of all matches of this
                               regex (effectively, split the match into a list of
                               characters and keep only the lowercase letters)
          z@?                 Find index of each letter in the lowercase alphabet
         M                    To that list of lists of indices, map this function:
'.X7                           Take a string of 7 periods
    RA_                        and replace the characters at all indices in the argument
       'O                      with O
                              Finally, autoprint the resulting list, with each item on
                              its own line (-l flag)

入力の変換方法のサンプルを次に示します。

"b.(ceg)"
["b" "." "(ceg)"]
[["b"] [] ["c" "e" "g"]]
[[1] [] [2 4 6]]
[".O....." "......." "..O.O.O"]

6

Pythonの295 94バイト

値インクのおかげで-1バイト

x=1
for i in input():
 if x:o=['.']*7
 if'@'<i:o[ord(i)-65]='O'
 if'*'>i:x=i>'('
 if x:print o

オンラインでお試しください!またはすべてのテストケースを試す

説明

'@'<i正しい位置のby をi置き換える文字であるかどうかを確認することです。かどうかを確認することです、されている場合、括弧がある置く上の印刷/消去を防ぐためにするとき、それは置く上の印刷/クリアを再度有効。 ときに何も変更されません、と印刷されます。 文字の順序は、ASCIIコードで指定されます。ここで、.O
'*'>iix=i>'('0xoi==')'1xo
i=='.''.......'
'('<')'<'*'<'.'<'@'<'A'


ああ、私はそのコメントを逃しました。nvm。
キントピア

コンマを捨てる:['.']*7。おそらく、コンマを必要とするタプルを使用していたときからのホールドオーバーです。また、私は間違っているかもしれませんが、これは['O', '.', '.', '.', '.', '.', '.']行ごとに配列を出力するようで、それが許可されているかどうかわかりませんか?
バリューインク


バイトの変更について言及し、TIOリンクを変更しましたが、投稿にリストされているコードは同じままです。V
Value Ink

1
@ValueInk¯\ _(ツ)_ /¯–
ロッド

4

バッチ、209バイト

@set s=%1
@set p=)
@for %%n in (a b c d e f g)do @set %%n=.
:g
@if %s:~,1% lss @ (set "p=%s:~,1%")else set %s:~,1%=O
@set s=%s:~1%
@if %p%==( goto g
@echo %a%%b%%c%%d%%e%%f%%g%
@if not "%s%"=="" %0 %s%

最後に表示された記号が(


4

ローダ97 78 76バイト

{search`\(\w+\)|.`|{|c|seq 65,71|{|l|["O"]if[chr(l)in c]else["."]}_;["
"]}_}

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

これは、ストリームから入力を読み取る匿名関数です。次のように使用しますmain { f={...}; push("ABCD") | f() }。ETHproductionsの答えからの正規表現を使用します。

ゴルフをしていない:

{
    search(`\(\w+\)|.`) | for chord do
        seq(ord("A"), ord("G")) | for note do
            if [ chr(note) in chord ] do
                push("O")
            else
                push(".")
            done
        done
        push("\n")
    done
}

前の答え:

f s{(s/"(?=([^()]*(\\([^()]*\\))?)*$)")|{|c|seq 65,71|{|l|["O"]if[chr(l)in c]else["."]}_;["
"]}_}

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

次の文字列に一致する括弧のみが含まれる場所で、指定された文字列を分割することで機能します。次に、コードごとに、考えられる音符を繰り返し処理しO、音符がコードのメンバーであるかどうかを印刷し.ます。


4

JavaScript(ES6)、86 85 76バイト

@Neilのおかげで9バイト節約

let f =
s=>s.replace(r=/\(\w+\)|./g,x=>`ABCDEFG
`.replace(r,c=>x.match(c)?"O":"."))
<input oninput="if(/^([A-G.]|\([A-G]+\))+$/.test(value))O.textContent=f(value)"><br>
<pre id=O></pre>

説明

最初に、出力の各行を形成するもの、つまりコード、およびコードの一部ではない文字を照合します。次に、各行について、文字列を取得し、その行内のABCDEFG\n各非改行文字をO、行に含まれている場合と.そうでない場合に置き換えます。


末尾の改行が許容される場合、を使用して8バイトを保存できますs=>s.replace(r=/\(\w+\)|./g,x=>`ABCDEFG\n`.replace(r,c=>x.match(c)?"O":"."))
ニール

@ニールワオ、それはすごい:
ETHproductions

えっ、今、私は再びそれを測定すること、それが保存10バイトでなければなりません...
ニール

すること\)ができます.か?
l4m2

2

JavaScript(ES6)、118 116 114バイト

f=([c,...t],s)=>c?((s?0:x=[...'.......'],c='ABCDEFG)('.indexOf(c))>6?c-7:(x[c]='O',s))?f(t,1):x.join``+`
`+f(t):''

テストケース


2

ルビー、78 75 71バイト

->x{x.scan(/\(\w+\)|./).map{|x|l=?.*7
x.bytes{|x|x>47?l[x-65]=?O:1};l}}

文字列の配列を返します。

Ungolfed +説明

def boxes string
  string.scan(/\(\w+\)|./)    # Split the string into an array of chords.
  .map do |chord|             # Replace each chord with...
    line = '.' * 7            # a line, where by default each character is a '.',
    chord.bytes do |note|     # but for each note in the chord...
      if note > '.'.ord       # (if it is in fact a note and not a dot or paren)
        line[note-65] = 'O'   # replace the corresponding dot with an 'O'.
      end
    end
    line               
  end
end

試してみてくださいx.gsub(...){l=?.*7;$&.bytes{...};l+$/}(スワップscangsub削除をmap、最初に飛ばし|x|、あなたが使用することができますので、$&3つのバイトを保存し、代わりに、複数行の文字列を返すために、最後の正規表現のマッチにアクセスすること)。($/デフォルトでは改行にもマップされます。)
値インク

1

PHP、171バイト

preg_match_all('#[A-G\.]|\([A-G]+\)#',$argv[1],$m);foreach($m[0]as$l){if($l=='.')echo".......";else foreach([A,B,C,D,E,F,G]as$a)echo strpos($l,$a)!==false?O:'.';echo"\n";}

壊す :

preg_match_all('#[A-G\.]|\([A-G]+\)#',$argv[1],$m); // Matches either one character in the range [A-G.] OR multiple [A-G] characters between parentheses
foreach($m[0]as$l)                                  // For each match :
    if($l=='.')                                     //   If no note is played
        echo".......";                              //     Echo empty music line
    else                                            //   Else
        foreach([A,B,C,D,E,F,G]as$a)                //     For each note in the [A-G] range
            echo strpos($l,$a)!==false?O:'.';       //       Echo O i the note is played, . if not
    echo"\n";                                       //  Echo new line
}

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


1

網膜、120バイト

O`(?<=\([^)]*)[^)]
T`L.`d
(?<=\([^)]*)\d
$*x 
\)
m¶
+`\b(x+) \1(x+) m
$1 m$2 
 m?x

T`x m(`.\O_
\d
$*.O¶
¶
6$*.¶
%7>`.

ゴルフの余地はあると思いますが、今はうまく機能しているので、後でゴルフをしようと思います。

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

使い方

基本的に、プログラムは各文字を数字に変更してからO、行のその位置にaを割り当てることで機能します。にマップABCDEFG.します01234569ます。

単一のノート行を生成するにはO、対応する番号の後に. sの後に行を追加し、行を7文字の長さまでパディング。

ただし、和音は少しややこしいです。同様のプロセスが使用されますが、番号は増分に変換する必要があります。つまり、和音の最初の音は(何でも)、2番目は1番目の後のX位置、3番目はその後のY位置などです。

コード

O`(?<=\([^)]*)[^)]

コード内のすべてのキャラクターをソートすることから始めます。

T`L.`d

文字から数字への音訳(マッピング)を実行します。

(?<=\([^)]*)\d
$*x 

括弧内のすべての数字を単項表現に置き換えます(使用 x s)で、その後にスペースを続けます。

\)
m¶

すべての閉じ括弧を、mその後に改行を付けて置き換えます。m今後ループのための一種のマーカーとして使用されます。

+`\b(x+) \1(x+) m
$1 m$2 

これは、交換できなくなるまでループする交換ステージです。xの前のsの最後の2つのシーケンスを取り、m2番目から1番目を引き、m後ろに移動します。mこの操作は右から左に実行する必要があるため、マーカーが必要です。

 m?x

最初のxシーケンスを除く各シーケンスの最初を削除します。

T`x m(`.\O_

T交換することによりransliterate x.した空間、Oおよび削除m(

この時点で、コードのすべてのラインが作成されました。次に、単一音符の行を作成する必要があります。

\d
$*.O¶

各桁をその数.のsで置き換え、その後にO改行と改行を続けます。

¶
6$*.¶
%7>`.

.sを右に追加して、各行の長さを7 にします。これ.は、各行の最後に6を追加し(各行には少なくとも1つの他の文字があります)、各行の最初の7の後のすべての文字を何も置き換えないことで機能します。(.9にマップOされるため、これらの行で切り取られます)



0

Perl 5-78 + 1(フラグ)+ 2(入力引用符)= 81バイト

for(;/(\([a-g]+\)|[a-g\.])/g;){$i=$1;print$i=~/$_/?'o':'.'for(a..g);print"\n"}

次のように実行できます:

perl -n <name of file holding script> <<< <input in quotations>

引用符で囲まれた入力は2バイト余分にカウントされると思いませんか?間違っている可能性があります。それ以外の場合、このことについてメタコンセンサスがあるかもしれません。
Okx

@Okxはバイトカウントを更新しました。それが追加されたかどうかは
わかり

0

ルビー、68バイト

->s{w=?.*m=7
s.bytes{|i|i>64?w[i-65]=?O:m=i!=40;m&&(puts w;w=?.*7)}}

アイデアは、文字.......を見つけるたびに文字列を変更し、それを出力してリセットすることです。ただし、括弧の外にいる場合のみです。(出力をオフにします。)そして.両方とも出力をオン/オフにしますが、後者はブラケット内では検出されないため重要ではありません。

テストプログラムでゴルフをしていない

f=->s{w=?.*m=7              #set m to a truthy value (7) and w to seven .'s
  s.bytes{|i|               #for each byte in the string
    i>64?w[i-65]=?O:m=i!=40 #if a letter, modify the appropriate character of w ELSE set m to false if inside brackets, true otherwise.
    m&&(puts w;w=?.*7)      #if m is true, output the contents of w and reset to seven .'s
  }
}

p 1
f["B(ACE)D"]
p 2
f["B"]
p 3
f["GGABC"]
p 4
f["A..F.C(DA)."]
p 5
f[".(ABCDEF)"]

0

Python 3、94バイト

匿名関数

import re
lambda s:[''.join('.O'[c in x]for c in'ABCDEFG')for x in re.findall(r'\(\w+\)|.',s)]

0

Haskell、101バイト

c#s|elem c s=c|1<3='.'
s?r=map(#s)"ABCDEFG":p r
p('(':r)|(x,_:t)<-span(')'<)r=x?t
p(x:r)=[x]?r
p e=[]

オンラインでお試しください!使用法:p "AB.(CA)D"。文字列のリストを返します。

説明:

関数pは文字列を再帰的に処理します。それは開口部ブラケットを見つけた場合'('、その後(x,_:t)<-span(')'<)r、残りの文字列を分割r文字列にx閉じ括弧の発生前')'tそれの後。それ以外の場合、現在の文字xは文字列に変換されます[x]。どちらの場合も、関数?は現在のノートの文字列と残りの文字列で呼び出されます。 ?は、関数#を文字列にマップします"ABCDEFG"。ここ#で、現在のノートの文字列にないすべての文字がに置き換えられ'.'ます。結果のオルゴール行はp、残りのリストの再帰呼び出しの前に追加されますr


0

Retina 0.8.2、52バイト

\(\w+\)|.
abcdefg$&¶
+`([a-g])(.*)\1
O$2
T`().l`___.

オンラインでお試しください!小文字で入力します。説明:

\(\w+\)|.
abcdefg$&¶

音楽を和音または音符に分割し、同等の音符のリストを追加して出力の構築を開始します。

+`([a-g])(.*)\1
O$2

各コードの各ノートについて、出力をに変更Oし、コードからノートを削除します。

T`().l`___.

無関係な音楽をすべて削除し、一致しないノートをすべて空に変更します。


0

PHP、93バイト

for($s=$t="
.......";$c=ord($argn[$i++]);$d||$s=$t.!print$s)$c<65?$c-46&&$d=~$c&1:$s[$c&7]=O;

でパイプとして実行する-nR、オンラインで試してください

壊す

for($s=$t="\n.......";      // init
    $c=ord($argn[$i++]);    // loop through characters
    $d||                        // 2. if chord flag is unset
        $s=$t.!print$s)             // then print and reset chord
    $c<65                       // 1. if not note
        ?$c-46                      // and not dot
            &&$d=~$c&1              // then set or clear chord flag
        :$s[$c&7]=O             // else set note in chord
    ;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.