Изготовление музыкальных шкатулок

23

Ваша задача - взять последовательность символов (музыку) в качестве входных данных (в функции или программе) и напечатать (или вернуть) музыку так, как она выглядит в музыкальной шкатулке.

Вы получите только символы в ABCDEFG.()качестве входных данных, а ввод никогда не будет пустым. Вы также можете получать буквы в нижнем регистре, если вы этого хотите.

Это пустая музыкальная шкатулка длиной 3:

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

Как видите, длина строки составляет 7 символов, а поскольку длина музыкальной шкатулки равна 3, у нас есть 3 строки. Здесь есть только .s, так как музыкальная шкатулка пуста. Давайте добавим немного музыки в это!

Сначала мы создаем музыкальную шкатулку. В этом примере вход будет CDAG.DAG.

Длина CDAG.DAG8, поэтому нам нужна музыкальная шкатулка длиной 8:

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

Затем мы читаем ввод, по одному символу за раз, и помещаем 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)

Этот аккорд инструктирует нас играть ноты A, Cи 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.

Конечный / ведущий пробел на выходе разрешен.

Поскольку это , выигрывает самый короткий код!

Okx
источник
может ли музыкальная строка содержать ()дважды (например AB(CD)E(FG):)?
г-н Xcoder
@ Mr.Xcoder Да, это возможно.
Okx
Может ли вывод быть списком / массивом символов?
Род
@ Род уверен, согласно стандартам
PPCG
Мы гарантируем, что не получим две одинаковые ноты в одном аккорде?
Business Cat

Ответы:

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"]
DLosc
источник
6

Python 2 , 95 94 байта

-1 байт благодаря 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

Попробуйте онлайн! или попробуйте все тестовые случаи

объяснение

'@'<iчтобы проверить , если iэто письмо, заменив .на Oна правильном положении.
'*'>iчтобы проверить, iявляется скобкой, если он x=i>'('поставит 0на , xчтобы предотвратить печать / очистку o, когда i==')'он будет ставить 1на xповторном включении печати / очистки o.
Когда i=='.'ничего не изменится и '.......'будет напечатано.
Порядок charater определяется кодом ASCII, где'('<')'<'*'<'.'<'@'<'A'

прут
источник
о, я пропустил этот комментарий. NVM.
Quintopia
Канава запятой: ['.']*7. Возможно, это пережиток того времени, когда вы использовали кортеж, который потребовал бы запятую. Кроме того, я могу ошибаться, но, похоже, это выводит массив ['O', '.', '.', '.', '.', '.', '.']на строку, и я не уверен, разрешено ли это?
Value Ink
@ValueInk да, OP разрешено
Род
Вы упомянули изменение байта и изменили свою ссылку 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

Röda , 97 78 76 байт

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

Попробуйте онлайн!

Это анонимная функция, которая читает входные данные из потока. Используйте его так: main { f={...}; push("ABCD") | f() }. Он использует регулярное выражение из ответа 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
}

Предыдущий ответ:

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

Попробуйте онлайн!

Он работает, разбивая данную строку в местах, где следующая строка содержит только совпадающие скобки. Затем для каждого аккорда он просматривает возможные ноты и печатает, Oесли нота является членом аккорда, и в .противном случае.

fergusq
источник
4

JavaScript (ES6), 86 85 76 байт

Сохранено 9 байтов благодаря @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>

объяснение

Сначала мы сопоставляем то, что будет формировать каждую строку выходных данных: аккорды и символы, которые не являются частью аккорда. Затем для каждой строки мы берем строку ABCDEFG\nи заменяем каждый символ, не являющийся символом новой строки, на нее, Oесли строка содержит ее, и на .иное.

ETHproductions
источник
Если завершающий перевод строки является приемлемым, вы можете сохранить 8 байтов, используя s=>s.replace(r=/\(\w+\)|./g,x=>`ABCDEFG\n`.replace(r,c=>x.match(c)?"O":".")).
Нил
@Neil Wow, это удивительно :-)
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):''

Контрольные примеры

Arnauld
источник
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
м-chrzan
источник
Попробуйте x.gsub(...){l=?.*7;$&.bytes{...};l+$/}(своп scanс gsub, REMOVE map, и пропустить первый , |x|так как вы можете использовать , $&чтобы получить доступ последнего матча регулярного выражения) , чтобы сохранить 3 байт и возвращает строку из нескольких строк вместо этого. ( $/По умолчанию также отображается на новую
Значение Ink
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
}

Попробуй это здесь!

roberto06
источник
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эту позицию в строке. Это сопоставляется ABCDEFG.с 01234569.

Чтобы сгенерировать одиночные строки примечания, все, что нужно сделать, это поставить Oпосле соответствующего числа .s, а затем добавить строку длиной до 7 символов.

Тем не менее, аккорды немного сложнее сделать. Аналогичный процесс используется, но числа должны быть переведены в приращения, то есть первая нота в аккорде (что угодно), вторая позиция X после первой, третья позиция Y после этого и т. Д.

Код

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

Начните с сортировки всех символов в аккордах.

T`L.`d

Выполните транслитерацию (отображение) от букв к цифрам.

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

Замените все цифры в скобках унарным представлением (используя xs), а затем пробел.

\)
m¶

Замените все закрывающие скобки с mпоследующим переводом строки. mБудет использоваться в качестве маркеров сортов для предстоящего цикла:

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

Это этап замены, который повторяется до тех пор, пока он больше не сможет заменить. Он принимает последние две последовательности xs перед an mи вычитает первую из второй, перемещая mназад. Маркер mнеобходим, потому что он должен выполнять эту операцию справа налево.

 m?x

Удалите первое xв каждой последовательности, кроме первого.

T`x m(`.\O_

Transliterate путем замены xс ., с пространством O, и удаление mи (.

На данный момент все строки для аккордов были созданы. Теперь должны быть созданы одиночные ноты.

\d
$*.O¶

Замените каждую цифру таким количеством .s, за которым следуют Oи новая строка.

¶
6$*.¶
%7>`.

Дополните каждую строку длиной 7, добавив .s справа. Это работает, добавляя 6 .с в конце каждой строки (каждая строка будет иметь по крайней мере 1 другой символ), затем заменяя каждый символ после первых 7 в каждой строке ничем. (Поскольку .карты на 9, Oбудут вырезаны на этих линиях)

Бизнес Кот
источник
1

Perl, 87 71 45 + 2 ( -nlфлаг) = 47 байт

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

С помощью:

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

Попробуйте это на Ideone.

Денис Ибаев
источник
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>
CraigR8806
источник
Не думаете ли вы, что ввод в кавычках будет считаться 2 дополнительных байта? Я могу ошибаться, так как может быть мета-консенсус по этому вопросу, утверждая иначе.
Okx
@Okx обновил мой счет. Не был уверен, добавил ли он к нему, все еще новенький здесь :)
CraigR8806
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)"]
Уровень реки St
источник
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)]
RootTwo
источник
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.

Laikoni
источник
0

Сетчатка 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
    ;
Titus
источник