Müzik Kutuları Yapımı


23

Göreviniz girdi (işlev veya programda) olarak bir dizi karakter (müzik) almak ve müziği bir müzik kutusunda göründüğü gibi yazdırmak (veya geri vermek).

Karakterleri yalnızca ABCDEFG.()giriş olarak alacaksınız ve giriş asla boş bırakılmayacak. İsterseniz harfleri küçük harf olarak da alabilirsiniz.

Bu, uzunluğu 3 olan boş bir müzik kutusudur:

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

Gördüğünüz gibi, satırlar 7 karakter uzunluğunda ve müzik kutusunun uzunluğu 3 olduğundan 3 satırımız var. Burada sadece .s var, çünkü müzik kutusu boş. Biraz müzik koyalım!

İlk önce, müzik kutusunu yarattık. Bu örnekte, giriş olacaktır CDAG.DAG.

Uzunluğu CDAG.DAG8, bu yüzden 8 uzunluğunda bir müzik kutusuna ihtiyacımız var:

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

Ardından girişi, her seferinde bir karakter okur Ove ilgili konumuna yerleştiririz.

İlk karakter Cve her notun yeri buna eşdeğerdir (netlik için boşluk ekledim):

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

Girilen karakter a ise .boş satır yazdırırız........

Böylece, Cbirlikte 3. karakter olacaktır. En üstteki müzik kutumuza koyalım:

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

Bu işlemi diğer tüm karakterler için tekrarlayacağız (parantez içindeki metin sadece notu göstermek içindir, çıktısını almamalısınız):

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

Biz başka bir karakter kullanırsanız müzik kutuları eser, nasıl Çünkü O, .ve <insert newline here>böyle bir mekan olarak, bizim çıktıda, o zaman doğru müzik çalmıyor!

Bu bir akor:

(ACE)

Bu akor notaları çalmak için bize talimat olduğunu A, Cve Eaynı zamanda. .Bir akorda hiç duraklama olmaz (yani a ).

Bu nasıl yazılır:

O.O.O...

Ve bu müzikte nasıl göründüğü: B(ACE)D

Bir akorda asla bir akor almayacaksınız, yani bu geçerli olmayacak: (AB(CD)EF)ya da bu: A(B())ve akor boş olmayacak, yani bu geçerli olmayacak:A()B

Asla geçersiz bir girdi almayacaksınız.

Örnekler:

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.

Çıktıdaki izler / ana boşluklara izin verilir.

Bu olduğu için en kısa kod kazanır!


Bir müzik dize ()iki kez içerebilir (örneğin AB(CD)E(FG):) ??
Bay Xcoder

@ Mr.Xcoder Evet, olabilir.
Okx

Çıktı bir liste / karakter dizisi olabilir mi?
Rod

@PPCG standartlarına göre emin
Okx

Aynı notadan ikisini aynı akorda almama garantisi veriyor muyuz?
Business Cat

Yanıtlar:


0

Pip , 29 bayt

28 baytlık kod, -lbayrak için +1 .

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

Harfleri küçük harflerle komut satırı argümanı olarak alır. Çevrimiçi deneyin!

açıklama

                              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)

Girişin nasıl dönüştürüldüğüne dair bir örnek:

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

6

Python 2 , 95 94 bayt

Value Ink sayesinde -1 bayt

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

Çevrimiçi deneyin! veya Tüm test durumlarını deneyin

açıklama

'@'<iolmadığını kontrol etmektir iyerini bir mektup .ile Osağ açık konumuna getirin.
'*'>iolmadığını kontrol etmektir iEğer öyleyse, bir parantez olduğunu x=i>'('koyacağız 0üzerinde xbaskı / açıklığa önlemek için ozaman, i==')'o koyacağız, 1üzerinde xyeniden etkinleştirme baskı / temizlenmesini o.
Ne zaman i=='.'hiçbir şey değişecek ve '.......'yazdırılacaktır.
Karakter sırası, ASCII koduyla verilir;'('<')'<'*'<'.'<'@'<'A'


oh bu yorumu kaçırdım. nvm.
quintopia

Virgül Hendek: ['.']*7. Muhtemelen virgül gerektiren bir tuple kullandığınız zamandan kalma bir yer. Ayrıca, hatalı olabilirim, ancak bu ['O', '.', '.', '.', '.', '.', '.']satır başına bir dizi çıkarıyor gibi görünüyor ve buna izin verilip verilmediğinden emin değilim.
Value Ink


Bayt değişiminden bahsettiniz ve TIO bağlantınızı değiştirdiniz, ancak gönderinizde listelenen kod hala aynı: V
Value Ink

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

4

Toplu iş, 209 bayt

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

Harfleri biriktirerek çalışır ve görülen son simge bir değilse satırın çıktısını alın (.


4

Röda , 97 78 76 bayt

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

Çevrimiçi deneyin!

Akıştan girişi okuyan anonim bir işlevdir. Bu şekilde kullanın: main { f={...}; push("ABCD") | f() }. ETHproductions'un cevabındaki regex'i kullanıyor.

Ungolfed:

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

Önceki cevap:

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

Çevrimiçi deneyin!

Verilen dizgiyi aşağıdaki dizginin sadece eşleşen parantez içerdiği yerlere bölerek çalışır. Daha sonra, her akor için olası notaları tekrar eder ve Onota akorun bir üyesiyse basar ve .başka şekilde basar .


4

JavaScript (ES6), 86 85 76 bayt

@Neil sayesinde 9 bayt kaydedildi

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>

açıklama

İlk önce, çıktının her bir satırını oluşturacak olanla eşleşiyoruz: akorlar ve bir akorun parçası olmayan karakterler. Daha sonra, her satır için dizeyi alırız ABCDEFG\nve içindeki her yeni satır dışı karakteri bir Osatır içeriyorsa, yerine .başka bir karakterle değiştiririz .


Sondaki yeni satır kabul edilebilirse, 8 bayt kullanarak tasarruf edebilirsiniz s=>s.replace(r=/\(\w+\)|./g,x=>`ABCDEFG\n`.replace(r,c=>x.match(c)?"O":".")).
Neil

@Neil Wow, bu inanılmaz :-)
ETHproductions

Huh, şimdi tekrar ölçtüm, 10 baytlık bir tasarruf olmalı ...
Neil

Can \)olmak .?
l4m2

2

JavaScript (ES6), 118 116 114 bayt

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

Test durumları


2

Ruby, 78 75 71 bayt

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

Bir dizi dizeyi döndürür.

Ungolfed + açıklama

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

Deneyin x.gsub(...){l=?.*7;$&.bytes{...};l+$/}(takas scanile gsubkaldır, mapve ilk atlama |x|kullanabilirsiniz beri $&geçen regex maç erişmek için) 3 bayt kaydetmek ve bunun yerine bir çok satırlı dize döndürmek için. (Ayrıca $/varsayılan olarak yeni bir satıra eşlenir.)
Value Ink

1

PHP, 171 bayt

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

Yıkmak :

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
}

Burada dene!


1

Retina , 120 bayt

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

Eminim golf oynamak için yer vardır, ama şimdi çalışıyor, bu yüzden daha sonra golf oynamaya çalışacağım.

Çevrimiçi deneyin!

Nasıl çalışır

Temel olarak, program her karakteri bir sayı olarak değiştirip ardından Obir çizgide bu konuma bir atama yaparak çalışır. Bu haritalar ABCDEFG.için 01234569.

Tek nota çizgileri oluşturmak için tek yapılması gereken O, karşılık gelen .s sayısından sonra koymak , sonra satırı 7 karakter uzunluğunda bırakmaktır.

Ancak, akorlar yapmak biraz zor. Benzer bir işlem kullanılır, ancak sayıların artışlara çevrilmesi gerekir, yani akordaki ilk nota (her neyse), ikincisi X'den sonraki X pozisyonları, üçüncüsü bundan sonraki Y pozisyonları vb.

kod

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

Akor içindeki tüm karakterleri sıralayarak başlayın.

T`L.`d

Harflerden sayılara harf çevirisi (eşleme) yapın.

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

Parantez içindeki tüm rakamları tek bir gösterimle ( xs'yi kullanarak ) ve ardından boşluk bırakın.

\)
m¶

Tüm kapatma braketlerini mardından yeni bir satırla değiştirin. Bu mgelecek döngü için bir çeşit marker olarak kullanılacaktır:

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

Bu artık değiştirilemeyecek kadar döngüye giren yeni bir aşama. Bu son iki dizinin alan xbir önceki s mve hareketli, ikinci ilk çıkarır mgeri. İşaretçi mgereklidir, çünkü bu işlemi sağdan sola yapmak zorundadır.

 m?x

İlki xhariç her sekanstaki ilki çıkarın .

T`x m(`.\O_

Tdeğiştirerek ransliterate xile .birlikte uzayda, Ove silme mve (.

Bu noktada, akorlar için tüm hatlar yaratıldı. Şimdi tek nota çizgileri oluşturulmalı.

\d
$*.O¶

Her basamağı bu kadar .s ile değiştirin , ardından bir Ove yeni satır kullanın.

¶
6$*.¶
%7>`.

.Sağa s ekleyerek her çizgiyi 7 uzunluğuna kadar doldurun. Bu ., her satırın sonuna 6 saniye ekleyerek çalışır (her satır en az 1 başka karaktere sahip olur), ardından her satırdaki ilk 7'den sonra gelen karakterleri hiçbir şey olmadan değiştirir. ( .9'a eşlendiğinden beri O, bu satırlarda kesilecek)


1

Perl, 87 71 45 + 2 ( -nlbayrak) = 47 bayt

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

Kullanımı:

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

Ideone'da dene.


0

Perl 5 - 78 + 1 (bayrak) + 2 (Giriş Tırnakları) = 81 Bayt

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

Bu şekilde çalıştırılabilir:

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

Tırnak içindeki girişin 2 fazla bayt sayılacağını düşünmüyor musunuz? Aksi halde bu konuda meta bir fikir birliği olabileceğinden yanılmış olabilirim.
Okx

@Okx bytecount'umu güncelledi. O ekledi emin değildi, hala biraz burada yeni :)
CraigR8806

0

Ruby, 68 bayt

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

Fikir, .......her mektup bulduğumuzda dizgiyi değiştirmek , sonra onu basmak ve sıfırlamak, ancak yalnızca parantezin dışına çıktığımızda. (çıkışı kapatır. )ve .her ikisi de çıkışı açık / kapalı konuma getirir, ancak ikincisi bir braketin içinde asla bulunmayacağı için önemsizdir.

Test programında Ungolfed

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 bayt

Anonim bir işlev

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

0

Haskell , 101 bayt

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

Çevrimiçi deneyin! Kullanımı: p "AB.(CA)D". Dizelerin bir listesini döndürür.

Açıklama:

İşlev, pdizginin üzerinde yinelenir. Bulduğu takdirde bir açılış braket '('sonra (x,_:t)<-span(')'<)rgerisi dizesini bölmeler rdizeleri içine xayraç verilmeden önceki ')'ve tondan sonra. Aksi halde, geçerli karakter xbir dizgeye dönüşür [x]. Her iki durumda da, işlev ?geçerli not dizesi ve dinlenme dizesi ile çağrılır. ?işlevi #, dizgede eşleştirir; "ABCDEFG"burada #geçerli not dizesinde bulunmayan tüm karakterleri değiştirir '.'. Elde edilen müzik kutusu çizgisi pdinlenme listesindeki özyinelemeli çağrı için hazırlanır r.


0

Retina 0.8.2 , 52 bayt

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

Çevrimiçi deneyin! Küçük harfle giriş yapar. Açıklama:

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

Müziği akorlara veya notalara bölün ve nota eşdeğerlerinin listesini ekleyerek çıktıyı oluşturmaya başlayın.

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

Her akordaki her nota için çıktıyı an olarak değiştirin Ove notayı akordan silin.

T`().l`___.

Artık tüm yabancı müzikleri silin ve eşleştirilmemiş tüm notları boş olarak değiştirin.


0

PHP, 93 bayt

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

Pipe ile koş -nRveya çevrimiçi dene .

Yıkmak

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
    ;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.