Realizzare scatole musicali


23

Il tuo compito è prendere una sequenza di caratteri (la musica) come input (in una funzione o programma) e stampare (o restituire) la musica come apparirebbe in un carillon.

Riceverai solo i caratteri ABCDEFG.()come input e l'input non sarà mai vuoto. Puoi anche ricevere le lettere in minuscolo, se lo desideri.

Questo è un carillon vuoto, di lunghezza 3:

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

Come puoi vedere, le linee sono lunghe 7 caratteri e poiché la lunghezza del carillon è 3, abbiamo 3 linee. Ci sono solo .qui, poiché il carillon è vuoto. Mettiamoci un po 'di musica!

Innanzitutto, creiamo il carillon. In questo esempio, l'input sarà CDAG.DAG.

La lunghezza di CDAG.DAGè 8, quindi abbiamo bisogno di un carillon di lunghezza 8:

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

Quindi, leggiamo l'input, un carattere alla volta, e posizioniamo un Onella sua rispettiva posizione.

Il primo carattere è Ce la posizione di ciascuna nota è equivalente a questa (ho aggiunto spazi per chiarezza):

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

Se il carattere di input è a ., stampiamo solo una riga vuota.......

Quindi, Csarebbe il terzo personaggio insieme. Mettiamolo nel nostro carillon in alto:

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

Ripeteremo questo processo per tutti gli altri caratteri (il testo tra parentesi è solo per mostrarti la nota, non dovresti emetterlo):

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

A causa di come funzionano i carillon, se usiamo un personaggio diverso da O, .e <insert newline here>, come uno spazio, nel nostro output, allora non riprodurrà la musica corretta!

Questo è un accordo:

(ACE)

Questo accordo ci sta istruendo a suonare le note A, Ce Eallo stesso tempo. Non ci sarà mai una pausa (cioè a .) in un accordo.

Ecco come sarebbe scritto:

O.O.O...

Ed è così che potrebbe apparire in musica: B(ACE)D

Non riceverai mai un accordo in un accordo, cioè questo non sarà valido: (AB(CD)EF)o questo: A(B())e l'accordo non sarà vuoto, cioè questo non sarà valido:A()B

Non riceverai mai un input non valido.

Esempi:

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.

È consentito il trailing / lead whitespace sull'output.

Dato che si tratta di , vince il codice più corto!


una stringa musicale può contenere ()due volte (ad es . AB(CD)E(FG):) ??
Mr. Xcoder

@ Mr.Xcoder Sì, può.
Okx,

L'output può essere un elenco / matrice di caratteri?
Rod

@Rod sicuro, secondo gli standard PPCG
Okx

Siamo sicuri di non avere due della stessa nota nello stesso accordo?
Business Cat

Risposte:


0

Pip , 29 byte

28 byte di codice, +1 per la -lbandiera.

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

Accetta l'input in minuscolo come argomento della riga di comando. Provalo online!

Spiegazione

                              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)

Ecco un esempio di come viene trasformato un input:

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

6

Python 2 , 95 94 byte

-1 byte grazie a 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

Provalo online! oppure Prova tutti i casi di test

Spiegazione

'@'<iè verificare se si itratta di una lettera, sostituendo il .con Onella posizione corretta.
'*'>iè quello di verificare se iè una parentesi, se si tratta x=i>'('metterà 0sulla xper evitare che la stampa / compensazione dei o, quando i==')', metterà 1sul xriattivare la stampa / compensazione dei o.
Quando i=='.'nulla verrà modificato e '.......'verrà stampato.
L'ordine dei caratteri è dato dal loro codice ASCII, dove'('<')'<'*'<'.'<'@'<'A'


oh ho perso quel commento. NVM.
Quintopia,

Fosso la virgola: ['.']*7. Forse è un blocco da quando stavi usando una tupla, che richiederebbe la virgola. Inoltre, potrei sbagliarmi, ma questo sembra generare un array ['O', '.', '.', '.', '.', '.', '.']per riga e non sono sicuro che sia consentito?
Value Ink


Hai citato la modifica del byte e modificato il tuo link TIO ma il codice elencato nel tuo post è sempre lo stesso: V
Value Ink

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

4

Lotto, 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%

Funziona accumulando lettere e producendo la linea se l'ultimo simbolo visto non era a (.


4

Röda , 97 78 76 byte

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

Provalo online!

È una funzione anonima che legge l'input dallo stream. Utilizzare in questo modo: main { f={...}; push("ABCD") | f() }. Usa la regex dalla risposta di 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
}

Risposta precedente:

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

Provalo online!

Funziona dividendo la stringa data in punti in cui la stringa seguente contiene solo parentesi corrispondenti. Quindi, per ogni accordo, scorre le possibili note e stampa Ose la nota è un membro dell'accordo e in .altro modo.


4

JavaScript (ES6), 86 85 76 byte

Salvataggio di 9 byte grazie a @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>

Spiegazione

Innanzitutto, abbiniamo ciò che formerà ogni riga dell'output: accordi e caratteri che non fanno parte di un accordo. Quindi, per ogni riga, prendiamo la stringa ABCDEFG\ne sostituiamo ogni carattere non newline con un Ose la riga lo contiene e un .altro.


Se una nuova riga finale è accettabile, è possibile salvare 8 byte utilizzando s=>s.replace(r=/\(\w+\)|./g,x=>`ABCDEFG\n`.replace(r,c=>x.match(c)?"O":".")).
Neil

@Neil Wow, è fantastico :-)
ETHproductions

Eh, ora che lo misuro di nuovo, dovrebbe essere un risparmio di 10 byte ...
Neil

Può \)essere .?
l4m2

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

Casi test


2

Rubino, 78 75 71 byte

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

Restituisce una matrice di stringhe.

Ungolfed + spiegazione

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

Prova x.gsub(...){l=?.*7;$&.bytes{...};l+$/}(scambia scancon gsub, rimuovi mape salta il primo |x|poiché puoi usare $&per accedere all'ultima regex match) per salvare 3 byte e restituire invece una stringa multi-linea. (Anche $/mappato su una nuova riga per impostazione predefinita.)
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";}

Abbattersi :

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
}

Provalo qui!


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

Sono sicuro che ci sia spazio per giocare a golf, ma ora funziona, quindi proverò a giocare a golf più tardi.

Provalo online!

Come funziona

Fondamentalmente, il programma funziona cambiando ciascun carattere in un numero, quindi assegnando Oa quella posizione in una riga. Si associa ABCDEFG.a 01234569.

Per generare le singole righe di nota, è sufficiente inserire una Odopo il numero corrispondente di .s, quindi riempire la riga di 7 caratteri.

Tuttavia, gli accordi sono un po 'più complicati da fare. Viene utilizzato un processo simile, ma i numeri devono essere tradotti in incrementi, ovvero la prima nota nell'accordo è (qualunque cosa), la seconda è posizioni X dopo la prima, la terza è posizioni Y dopo quella, ecc.

Codice

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

Inizia ordinando tutti i caratteri all'interno degli accordi.

T`L.`d

Esegue la traslitterazione (mappatura) da lettere a numeri.

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

Sostituisci tutte le cifre tra parentesi con una rappresentazione unaria (usando xs), seguita da uno spazio.

\)
m¶

Sostituire tutte le parentesi quadre con mseguito da una nuova riga. Il msarà usato come una sorta di marker per il prossimo loop:

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

Questa è una fase di sostituzione che va in loop fino a quando non può più sostituire. Prende le ultime due sequenze di xs prima di an me sottrae la prima dalla seconda, spostando la parte mposteriore. Il marker mè necessario perché deve eseguire questa operazione da destra a sinistra.

 m?x

Rimuovi il primo xin ogni sequenza tranne il primo.

T`x m(`.\O_

Transliterate sostituendo xcon ., spazio con O, ed eliminando me (.

A questo punto, sono state create tutte le linee per gli accordi. Ora devono essere create le righe a nota singola.

\d
$*.O¶

Sostituisci ogni cifra con tante .s, seguite da una Oe una nuova riga.

¶
6$*.¶
%7>`.

Riempi ciascuna linea alla lunghezza 7 aggiungendo .s a destra. Funziona aggiungendo 6 .s alla fine di ogni riga (ogni riga avrà almeno 1 altro carattere), quindi sostituendo ogni carattere dopo i primi 7 su ogni riga con niente. (Dato che le .mappe sono 9, Overranno tagliate su quelle linee)


1

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

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

usando:

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

Provalo su Ideone.


0

Perl 5 - 78 + 1 (flag) + 2 (virgolette di input) = 81 byte

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

Può essere eseguito in questo modo:

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

Non pensi che l'input tra virgolette valga come 2 byte extra? Potrei sbagliarmi, poiché potrebbe esserci un meta consenso su questo affermare il contrario.
Okx,

@Okx ha aggiornato il mio bytecount. Non ero sicuro se fosse stato aggiunto ad esso, ancora un po 'nuovo qui :)
CraigR8806

0

Rubino, 68 byte

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

L'idea è di modificare la stringa .......ogni volta che troviamo una lettera, quindi di emetterla e reimpostarla, ma solo quando siamo tra parentesi esterne. (disattiva l'output. )ed .entrambi commutano / lasciano attivo l'output, ma quest'ultimo non ha importanza in quanto non verrà mai trovato all'interno di una parentesi.

Non registrato nel programma di test

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

Una funzione anonima

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

Provalo online!Uso: p "AB.(CA)D". Restituisce un elenco di stringhe.

Spiegazione:

La funzione pricorre sulla stringa. Se trova una parentesi quadra aperta, '('allora (x,_:t)<-span(')'<)rsuddivide la stringa rimanente rnelle stringhe xprima che si verifichi la parentesi quadra chiusa ')'e tsuccessivamente. Altrimenti il ​​carattere corrente xviene trasformato in una stringa [x]. In entrambi i casi la funzione ?viene chiamata con la stringa di note corrente e la stringa di riposo. ?mappa la funzione #sulla stringa "ABCDEFG", dove #sostituisce tutti i caratteri che non sono nella stringa di note corrente con '.'. La linea del carillon risultante viene anteposta alla chiamata ricorsiva pnell'elenco di resto r.


0

Retina 0.8.2 , 52 byte

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

Provalo online! Riceve input in lettere minuscole. Spiegazione:

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

Dividi la musica in accordi o note e inizia a costruire l'output aggiungendo l'elenco degli equivalenti delle note.

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

Per ogni nota in ciascun accordo, cambia l'output in an Oed elimina la nota dall'accordo.

T`().l`___.

Elimina tutta la musica ora estranea e cambia tutte le note senza eguali in vuote.


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;

Esegui come pipe -nRo provalo online .

abbattersi

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
    ;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.