Membuat Kotak Musik


23

Tugas Anda adalah untuk mengambil urutan karakter (musik) sebagai input (dalam suatu fungsi atau program), dan mencetak (atau mengembalikan) musik seperti yang terlihat di kotak musik.

Anda hanya akan menerima karakter ABCDEFG.()sebagai input, dan input tidak akan pernah kosong. Anda juga dapat menerima surat dalam huruf kecil, jika Anda menginginkannya.

Ini adalah kotak musik kosong, dengan panjang 3:

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

Seperti yang Anda lihat, panjangnya 7 karakter, dan karena panjang kotak musiknya 3, kami punya 3 baris. Hanya ada .di sini, karena kotak musik kosong. Mari kita masukkan musik ke dalamnya!

Pertama, kami membuat kotak musik. Dalam contoh ini, inputnya adalah CDAG.DAG.

Panjangnya CDAG.DAG8, jadi kita perlu kotak musik dengan panjang 8:

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

Kemudian, kita membaca input, satu karakter pada satu waktu, dan menempatkan sebuah Odi posisi masing-masing.

Karakter pertama adalah C, dan lokasi setiap catatan setara dengan ini (saya menambahkan spasi untuk kejelasan):

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

Jika karakter input adalah a ., maka kita cukup mencetak baris kosong.......

Jadi, itu Cakan menjadi karakter ke-3. Mari kita taruh di kotak musik kita di atas:

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

Kami akan mengulangi proses ini untuk semua karakter lain (teks dalam tanda kurung hanya untuk menunjukkan catatan kepada Anda, Anda tidak harus menampilkannya):

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

Karena cara kerja kotak musik, jika kita menggunakan karakter selain O, .dan <insert newline here>, seperti spasi, di output kita, maka itu tidak akan memainkan musik yang benar!

Ini adalah kunci:

(ACE)

Akord ini memerintahkan kita untuk memainkan not A, Cdan Epada saat yang sama. Tidak akan ada jeda (yaitu a .) dalam sebuah akor.

Beginilah caranya ditulis:

O.O.O...

Dan beginilah tampilannya di musik: B(ACE)D

Anda tidak akan pernah menerima akor dalam akor, artinya ini tidak valid: (AB(CD)EF)atau ini A(B()):, dan akor tidak akan kosong, artinya ini tidak valid:A()B

Anda tidak akan pernah menerima input yang tidak valid.

Contoh:

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.

Trailing / spasi putih terkemuka pada output diizinkan.

Karena ini adalah , kode terpendek menang!


dapatkah sebuah string musik berisi ()dua kali (mis . AB(CD)E(FG):) ??
Tn. Xcoder

@ Mr.Xcoder Ya, itu bisa.
Okx

Bisakah output menjadi daftar / array karakter?
Rod

@Rod yakin, sesuai standar
PPCG

Apakah kami dijamin tidak mendapatkan dua nada yang sama dalam akor yang sama?
Bisnis Cat

Jawaban:


0

Pip , 29 byte

28 byte kode, +1 untuk -lbendera.

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

Mengambil input dalam huruf kecil sebagai argumen baris perintah. Cobalah online!

Penjelasan

                              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)

Berikut ini contoh bagaimana suatu input diubah:

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

6

Python 2 , 95 94 byte

-1 byte berkat Value Ink

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

Cobalah online! atau Coba semua test case

Penjelasan

'@'<iadalah untuk memeriksa apakah ihuruf, menggantikan .dengan Opada posisi yang tepat.
'*'>iadalah untuk memeriksa apakah iadalah kurung, jika x=i>'('akan menempatkan 0pada xuntuk mencegah pencetakan / kliring o, saat i==')', itu akan menempatkan 1pada xulang memungkinkan pencetakan / kliring o.
Ketika i=='.'tidak ada yang akan diubah, dan '.......'akan dicetak.
Perintah charater diberikan oleh kode ASCII mereka, di mana'('<')'<'*'<'.'<'@'<'A'


oh saya ketinggalan komentar itu. nvm.
kuintopia

Parit koma: ['.']*7. Mungkin itu adalah peninggalan dari saat Anda menggunakan tuple, yang akan membutuhkan koma. Juga, saya mungkin salah, tetapi ini sepertinya menghasilkan array ['O', '.', '.', '.', '.', '.', '.']per baris, dan saya tidak yakin apakah itu diizinkan?
Value Ink

@ ValueInk ya, OP diizinkan
Rod

Anda menyebutkan perubahan byte dan mengubah tautan TIO Anda, tetapi kode yang tercantum pada posting Anda masih sama: V
Value Ink

1
@NilaiInk ¯ \ _ (ツ) _ / ¯
Rod

4

Batch, 209 byte

@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%

Bekerja dengan mengumpulkan huruf dan mengeluarkan garis jika simbol terakhir yang terlihat bukan a (.


4

Röda , 97 78 76 byte

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

Cobalah online!

Ini adalah fungsi anonim yang membaca input dari aliran. Menggunakannya seperti ini: main { f={...}; push("ABCD") | f() }. Ia menggunakan regex dari jawaban ETHproductions.

Tidak Disatukan:

{
    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
}

Jawaban sebelumnya:

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

Cobalah online!

Ia bekerja dengan memisahkan string yang diberikan di tempat-tempat di mana string berikut hanya berisi tanda kurung yang cocok. Kemudian, untuk masing-masing akor, itu berganti melalui catatan yang mungkin dan mencetak Ojika catatan itu adalah anggota dari akor dan .sebaliknya.


4

JavaScript (ES6), 86 85 76 byte

Disimpan 9 byte berkat @Neil

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>

Penjelasan

Pertama, kami mencocokkan apa yang akan membentuk setiap baris output: akor, dan karakter yang bukan bagian dari akor. Lalu, untuk setiap baris, kami mengambil string ABCDEFG\ndan mengganti setiap karakter non-baris baru di dalamnya dengan Ojika baris berisi itu, dan .sebaliknya.


Jika trailing newline dapat diterima, Anda dapat menghemat 8 byte menggunakan s=>s.replace(r=/\(\w+\)|./g,x=>`ABCDEFG\n`.replace(r,c=>x.match(c)?"O":".")).
Neil

@Neil Wow, luar biasa :-)
ETHproduk

Huh, sekarang saya mengukurnya lagi, seharusnya penghematan 10 byte ...
Neil

Bisa \)menjadi .?
14m2

2

JavaScript (ES6), 118 116 114 byte

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):''

Uji kasus


2

Ruby, 78 75 71 byte

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

Mengembalikan array string.

Penjelasan + tidak dikelompokkan

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

Coba x.gsub(...){l=?.*7;$&.bytes{...};l+$/}(tukar scandengan gsub, hapus map, dan lewati yang pertama |x|karena Anda dapat menggunakan $&untuk mengakses pertandingan regex terakhir) untuk menyimpan 3 byte dan mengembalikan string multi-line sebagai gantinya. (Juga $/memetakan ke baris baru secara default.)
Value Ink

1

PHP, 171 byte

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";}

Kerusakan :

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
}

Coba di sini!


1

Retina , 120 byte

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>`.

Saya yakin ada ruang untuk bermain golf, tetapi ini berfungsi sekarang, jadi saya akan mencoba untuk bermain golf nanti.

Cobalah online!

Bagaimana itu bekerja

Pada dasarnya, program ini bekerja dengan mengubah setiap karakter menjadi angka, kemudian menetapkan a Oke posisi itu dalam satu baris. Itu peta ABCDEFG.ke 01234569.

Untuk menghasilkan baris nada tunggal, semua yang harus dilakukan adalah meletakkan Osetelah jumlah yang sesuai .s, kemudian pad garis sepanjang 7 karakter.

Namun, akor agak sulit dilakukan. Proses serupa digunakan, tetapi angka-angka harus diterjemahkan ke dalam kenaikan, yaitu nada pertama dalam akor adalah (apa pun), yang kedua adalah posisi X setelah yang pertama, yang ketiga adalah posisi Y setelah itu, dll.

Kode

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

Mulailah dengan menyortir semua karakter dalam akor.

T`L.`d

Lakukan transliterasi (pemetaan) dari huruf ke angka.

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

Ganti semua digit di dalam tanda kurung dengan representasi unary (menggunakan xs), diikuti oleh spasi.

\)
m¶

Ganti semua tanda kurung penutup dengan mdiikuti oleh baris baru. The makan digunakan sebagai penanda macam untuk loop datang:

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

Ini adalah tahap penggantian yang berulang sampai tidak dapat diganti lagi. Dibutuhkan dua urutan terakhir xsebelum m, dan kurangi yang pertama dari yang kedua, pindahkan ke mbelakang. Penandam diperlukan karena harus melakukan operasi ini dari kanan ke kiri.

 m?x

Hapus yang pertama xdi setiap urutan kecuali yang pertama.

T`x m(`.\O_

Transliterate dengan mengganti xdengan ., spasi dengan O, dan menghapusm dan (.

Pada titik ini, semua garis untuk akor telah dibuat. Sekarang baris not tunggal harus dibuat.

\d
$*.O¶

Ganti setiap digit dengan angka .s, diikuti oleh Odan dan baris baru.

¶
6$*.¶
%7>`.

Pad setiap baris dengan panjang 7 dengan menambahkan .s ke kanan. Ini bekerja dengan menambahkan 6 .s pada akhir setiap baris (setiap baris akan memiliki setidaknya 1 karakter lain), kemudian mengganti setiap karakter setelah 7 pertama pada setiap baris tanpa apa-apa. (Sejak .peta ke 9, Oakan dipotong pada garis itu)


1

Perl, 87 71 45 + 2 ( -nlbendera) = 47 byte

#!/usr/bin/env perl -nl
use v5.10;
say map$&=~/$_/i?O:".",a..g while/\(\w+\)|./g

Menggunakan:

perl -nlE 'say map$&=~/$_/i?O:".",a..g while/\(\w+\)|./g' <<< "A..F.C(DA)."

Cobalah di Ideone.


0

Perl 5 - 78 + 1 (bendera) + 2 (Kutipan Input) = 81 Bytes

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

Dapat dijalankan seperti ini:

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

Tidakkah Anda berpikir bahwa input dalam tanda kutip akan dihitung sebagai 2 byte tambahan? Saya mungkin salah, karena mungkin ada konsensus meta tentang pernyataan ini sebaliknya.
Okx

@Okx memperbarui bytecount saya. Tidak yakin apakah itu ditambahkan ke dalamnya, masih agak baru di sini :)
CraigR8806

0

Ruby, 68 byte

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

Idenya adalah untuk memodifikasi string .......setiap kali kita menemukan huruf, lalu mengeluarkan dan meresetnya, tetapi hanya ketika kita berada di luar tanda kurung. (mematikan keluaran. )dan. keduanya mengaktifkan / membiarkan keluaran aktif, tetapi yang terakhir tidak penting karena tidak akan pernah ditemukan di dalam braket.

Tidak digabungkan dalam program uji

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 byte

Fungsi anonim

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

0

Haskell , 101 byte

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=[]

Cobalah online! Pemakaian:p "AB.(CA)D" . Mengembalikan daftar string.

Penjelasan:

Fungsi pberulang pada string. Jika menemukan braket pembuka, '('maka (x,_:t)<-span(')'<)rpartisi string sisanya rke dalam string xsebelum terjadinya braket penutup ')'dan tsetelahnya. Kalau tidak, karakter saat xini diubah menjadi string [x]. Dalam kedua kasus fungsi ?tersebut disebut dengan string catatan saat ini dan string sisanya. ?memetakan fungsi di #atas string "ABCDEFG", tempat #mengganti semua karakter yang tidak ada dalam string catatan saat ini '.'. Baris kotak musik yang dihasilkan diawali dengan panggilan rekursif ppada daftar lainnya r.


0

Retina 0.8.2 , 52 byte

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

Cobalah online! Mengambil input dalam huruf kecil. Penjelasan:

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

Membagi musik menjadi akor atau not, dan mulai membangun output dengan menambahkan daftar setara nada.

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

Untuk setiap not pada setiap akor, ubah output menjadi O dan hapus catatan dari akor.

T`().l`___.

Hapus semua musik yang sekarang asing, dan ubah semua catatan yang tidak cocok menjadi kosong.


0

PHP, 93 byte

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

Jalankan sebagai pipa dengan -nRatau coba online .

kerusakan

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
    ;
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.