Spieluhren machen

23

Ihre Aufgabe ist es, eine Folge von Zeichen (die Musik) als Eingabe (in einer Funktion oder einem Programm) zu nehmen und die Musik so auszudrucken (oder zurückzugeben), wie es in einer Spieluhr aussehen würde.

Sie erhalten nur die Zeichen ABCDEFG.()als Eingabe, und die Eingabe wird niemals leer sein. Sie können die Buchstaben auch in Kleinbuchstaben erhalten, wenn Sie dies wünschen.

Dies ist eine leere Spieluhr mit der Länge 3:

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

Wie Sie sehen, sind die Zeilen 7 Zeichen lang, und da die Länge der Spieluhr 3 beträgt, haben wir 3 Zeilen. Es gibt nur .s hier, da die Spieluhr leer ist. Lass uns ein bisschen Musik reinlegen!

Zuerst erstellen wir die Spieluhr. In diesem Beispiel lautet die Eingabe CDAG.DAG.

Die Länge von CDAG.DAGist 8, also brauchen wir eine Spieluhr mit der Länge 8:

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

Dann lesen wir die Eingabe einzeln und platzieren eine Oan der entsprechenden Position.

Das erste Zeichen ist Cund die Position jeder Note ist gleichbedeutend damit (ich habe der Klarheit halber Leerzeichen hinzugefügt):

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

Wenn das eingegebene Zeichen a ist ., wird nur eine leere Zeile gedruckt.......

Das Cwäre also das dritte Zeichen. Lassen Sie es uns oben in unsere Spieluhr legen:

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

Wir werden diesen Vorgang für alle anderen Zeichen wiederholen (der Text in Klammern soll Ihnen nur die Notiz zeigen, das sollten Sie nicht ausgeben):

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

Weil, wie Musik - Boxen arbeiten, wenn wir ein anderes Zeichen als verwenden O, .und <insert newline here>, wie ein Raum, in unserer Ausgabe, dann wird es nicht die richtige Musik spielen!

Dies ist ein Akkord:

(ACE)

Dieser Akkord wird instruiert uns die Noten zu spielen A, Cund Ezur gleichen Zeit. Es wird niemals eine Pause (dh ein .) in einem Akkord geben.

So würde es geschrieben werden:

O.O.O...

Und so könnte es in der Musik aussehen: B(ACE)D

Sie erhalten niemals einen Akkord in einem Akkord, dh dies ist nicht gültig: (AB(CD)EF)oder dies:, A(B())und der Akkord ist nicht leer, dh dies ist nicht gültig:A()B

Sie erhalten niemals eine ungültige Eingabe.

Beispiele:

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.

Ein nachgestelltes / führendes Leerzeichen in der Ausgabe ist zulässig.

Da dies , gewinnt der kürzeste Code!

Okx
quelle
Kann eine Musiksaite ()zweimal enthalten (zB AB(CD)E(FG):)?
Mr. Xcoder
@ Mr.Xcoder Ja, das kann es.
Okx
Kann die Ausgabe eine Liste / ein Array von Zeichen sein?
Rod
@ Rod sicher, nach PPCG-Standards
Okx
Erhalten wir garantiert nicht zwei gleiche Noten im selben Akkord?
Business Cat

Antworten:

0

Pip , 29 Bytes

28 Byte Code, +1 für -lFlag.

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

Nimmt Eingaben in Kleinbuchstaben als Befehlszeilenargument. Probieren Sie es online!

Erläuterung

                              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)

Hier ist ein Beispiel, wie eine Eingabe transformiert wird:

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

Python 2 , 95 bis 94 Bytes

-1 Byte dank 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

Probieren Sie es online! oder Probieren Sie alle Testfälle aus

Erläuterung

'@'<iist zu überprüfen, ob ies sich um einen Buchstaben handelt, wobei der .durch Oan der richtigen Stelle ersetzt wird.
'*'>izu prüfen ist , ob ieine Klammer ist, wenn es x=i>'('wird gesetzt 0auf xden Druck / Clearing von zu verhindern o, wenn i==')'es gesetzt wird 1auf die xerneute Aktivierung der Druck / Clearing von o.
Wenn sich i=='.'nichts ändert und '.......'gedruckt wird.
Die Zeichenreihenfolge wird durch ihren ASCII-Code angegeben, wobei'('<')'<'*'<'.'<'@'<'A'

Stange
quelle
Oh, ich habe diesen Kommentar verpasst. nvm.
Quintopia
Graben Sie das Komma: ['.']*7. Vielleicht ist es ein Überbleibsel aus der Zeit, als Sie ein Tupel verwendeten, für das das Komma erforderlich wäre. Ich könnte mich auch irren, aber dies scheint ein Array ['O', '.', '.', '.', '.', '.', '.']pro Zeile auszugeben , und ich bin mir nicht sicher, ob das erlaubt ist?
Value Ink
@ValueInk yep, OP erlaubt
Rod
Sie erwähnten die Byte - Änderung und veränderten Ihren TIO Link aber der Code auf Ihrem Beitrag aufgelistet ist immer noch das gleiche: V
Wert Ink
1
@ValueInk ¯ \ _ (ツ) _ / ¯
Rod
4

Batch, 209 Bytes

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

Sammelt Buchstaben und gibt die Zeile aus, wenn das zuletzt gesehene Symbol nicht a war (.

Neil
quelle
4

Röda , 97 78 76 Bytes

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

Probieren Sie es online!

Es ist eine anonyme Funktion, die die Eingabe aus dem Stream liest. Verwenden Sie es wie folgt aus : main { f={...}; push("ABCD") | f() }. Es verwendet den regulären Ausdruck aus der Antwort von ETHproductions.

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
}

Vorherige Antwort:

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

Probieren Sie es online!

Es funktioniert, indem die angegebene Zeichenfolge an Stellen aufgeteilt wird, an denen die folgende Zeichenfolge nur übereinstimmende Klammern enthält. Dann durchläuft es für jeden Akkord mögliche Noten und druckt aus, Oob die Note ein Mitglied des Akkords ist und .ansonsten.

fergusq
quelle
4

JavaScript (ES6), 86 85 76 Byte

9 Bytes dank @Neil gespeichert

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>

Erläuterung

Erstens passen wir an, was jede Zeile der Ausgabe bildet: Akkorde und Zeichen, die nicht Teil eines Akkords sind. Dann nehmen wir für jede Zeile die Zeichenfolge ABCDEFG\nund ersetzen jedes Nicht-Zeilenumbruch-Zeichen darin durch ein, Owenn die Zeile es enthält, und ein .anderes.

ETHproductions
quelle
Wenn ein Zeilenumbruch akzeptabel ist, können Sie mit 8 Bytes sparen s=>s.replace(r=/\(\w+\)|./g,x=>`ABCDEFG\n`.replace(r,c=>x.match(c)?"O":".")).
Neil
@Neil Wow, das ist unglaublich :-)
ETHproductions
Huh, jetzt, wo ich es wieder messe, sollte es eine 10-Byte-Einsparung sein ...
Neil
Kann \)sein .?
14 m²,
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):''

Testfälle

Arnauld
quelle
2

Ruby, 78 75 71 Bytes

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

Gibt ein Array von Zeichenfolgen zurück.

Ungolfed + Erklärung

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
m-chrzan
quelle
Versuchen Sie x.gsub(...){l=?.*7;$&.bytes{...};l+$/}(tauschen Sie scanmit gsub, entfernen Sie mapund überspringen Sie den ersten, |x|da Sie $&auf die letzte Regex-Übereinstimmung zugreifen können ), um 3 Bytes zu sparen und stattdessen eine mehrzeilige Zeichenfolge zurückzugeben. ( $/Wird standardmäßig auch einer neuen Zeile zugeordnet.)
Value Ink
1

PHP, 171 Bytes

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

Nervenzusammenbruch :

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
}

Probieren Sie es hier aus!

roberto06
quelle
1

Netzhaut , 120 Bytes

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

Ich bin sicher, dass es Platz zum Golfen gibt, aber es funktioniert jetzt, also werde ich später versuchen, mehr Golf zu spielen.

Probieren Sie es online!

Wie es funktioniert

Grundsätzlich ändert das Programm jedes Zeichen in eine Zahl und weist Odieser Position in einer Zeile eine zu. Es ordnet ABCDEFG.zu 01234569.

Um die einzelnen Notenzeilen zu generieren, müssen Sie nur ein Zeichen Onach der entsprechenden Anzahl von .s einfügen und die Zeile dann mit 7 Zeichen auffüllen.

Die Akkorde sind jedoch etwas kniffliger. Ein ähnlicher Vorgang wird verwendet, aber die Zahlen müssen in Inkremente übersetzt werden, dh die erste Note im Akkord ist (was auch immer), die zweite ist die X-Position nach der ersten, die dritte ist die Y-Position danach usw.

Code

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

Sortieren Sie zunächst alle Zeichen in Akkorden.

T`L.`d

Führen Sie die Transliteration (Zuordnung) von Buchstaben zu Zahlen durch.

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

Ersetzen Sie alle Ziffern in Klammern durch eine unäre Darstellung (mit xs), gefolgt von einem Leerzeichen.

\)
m¶

Ersetzen Sie alle schließenden Klammern mdurch eine neue Zeile. Das mwird als eine Art Markierung für die kommende Schleife verwendet:

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

Dies ist eine Ersetzungsphase, die so lange wiederholt wird, bis sie nicht mehr ersetzt werden kann. Es dauert die letzten beiden Folgen von xs vor einem mund subtrahiert die erste von der zweiten, wobei der mRücken bewegt wird . Der Marker mwird benötigt, da er diesen Vorgang von rechts nach links ausführen muss.

 m?x

Entfernen Sie die erste xin jeder Sequenz mit Ausnahme der ersten.

T`x m(`.\O_

Tdurch Ersetzen xdurch ., Leerzeichen durch Ound Löschen von mund (.

Zu diesem Zeitpunkt wurden alle Linien für die Akkorde erstellt. Nun müssen die Einzelnotenlinien erstellt werden.

\d
$*.O¶

Ersetzen Sie jede Ziffer durch so viele .s, gefolgt von einem Ound einer neuen Zeile.

¶
6$*.¶
%7>`.

Füllen Sie jede Zeile auf die Länge 7 auf, indem Sie .rechts ein s hinzufügen . Dies funktioniert, indem .am Ende jeder Zeile 6 s hinzugefügt werden (jede Zeile enthält mindestens ein anderes Zeichen) und dann jedes Zeichen nach den ersten 7 in jeder Zeile durch nichts ersetzt wird. (Da .Karten bis 9, Owerden die auf diesen Linien ausgeschnitten)

Geschäfts-Katze
quelle
1

Perl, 87 71 45 + 2 ( -nlFlag) = 47 Bytes

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

Verwenden von:

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

Probieren Sie es auf Ideone.

Denis Ibaev
quelle
0

Perl 5 - 78 + 1 (Flag) + 2 (Eingabe-Anführungszeichen) = 81 Bytes

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

Kann so ausgeführt werden:

perl -n <name of file holding script> <<< <input in quotations>
CraigR8806
quelle
Glauben Sie nicht, dass die Eingabe in Anführungszeichen als 2 zusätzliche Bytes zählen würde? Ich kann mich irren, da möglicherweise ein Metakonsens darüber besteht, dass dies nicht der Fall ist.
Okx
@Okx hat mein bytecount aktualisiert. War nicht sicher, ob es hinzugefügt wurde, immer noch ein bisschen neu hier :)
CraigR8806
0

Ruby, 68 Bytes

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

Die Idee ist, die Zeichenfolge .......jedes Mal zu ändern, wenn wir einen Buchstaben finden, ihn dann ausgeben und zurücksetzen, aber nur, wenn wir uns außerhalb von Klammern befinden. (schaltet die Ausgabe aus. )und. beide schalten / lassen die Ausgabe an, aber letztere ist belanglos, da sie niemals in einer Klammer zu finden ist.

Ungolfed im Testprogramm

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)"]
Level River St
quelle
0

Python 3, 94 Bytes

Eine anonyme Funktion

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

Haskell , 101 Bytes

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

Probieren Sie es online! Verbrauch: p "AB.(CA)D". Gibt eine Liste von Zeichenfolgen zurück.

Erläuterung:

Die Funktion prekursiert über die Zeichenfolge. Wenn eine öffnende Klammer gefunden '('wird (x,_:t)<-span(')'<)r, wird die verbleibende Zeichenfolge vor und nach dem Auftreten der schließenden Klammer rin die Zeichenfolgen unterteilt . Andernfalls wird das aktuelle Zeichen in eine Zeichenfolge umgewandelt . In beiden Fällen wird die Funktion mit der aktuellen Notenfolge und der Restzeichenfolge aufgerufen. ordnet die Funktion der Zeichenfolge zu , wobei alle Zeichen, die nicht in der aktuellen Zeichenfolge enthalten sind, durch ersetzt werden . Die resultierende Musikboxzeile wird dem rekursiven Aufruf von in der Restliste vorangestellt .x')'tx[x]??#"ABCDEFG"#'.'pr

Laikoni
quelle
0

Retina 0.8.2 , 52 Bytes

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

Probieren Sie es online! Übernimmt die Eingabe in Kleinbuchstaben. Erläuterung:

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

Teilen Sie die Musik in Akkorde oder Noten auf und beginnen Sie mit dem Aufbau der Ausgabe, indem Sie die Liste der Notenäquivalente hinzufügen.

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

Ändern Sie für jede Note in jedem Akkord die Ausgabe in Ound löschen Sie die Note aus dem Akkord.

T`().l`___.

Löschen Sie alle jetzt irrelevanten Musiktitel und ändern Sie alle nicht zugeordneten Noten in leer.

Neil
quelle
0

PHP, 93 Bytes

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

Laufen Sie als Pipe mit -nRoder versuchen Sie es online .

Nervenzusammenbruch

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
    ;
Titus
quelle