制作音乐盒


23

您的任务是将一系列字符(音乐)作为输入(在函数或程序中),并按照音乐盒中的外观打印(或返回)音乐。

您将只接收字符ABCDEFG.()作为输入,并且输入永远不会为空。如果您愿意,您可能还会收到小写字母。

这是一个空的音乐盒,长度为3:

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

如您所见,这些行的长度为7个字符,并且由于音乐盒的长度为3,因此我们有3行。.因为音乐盒为空,所以这里只有。让我们放一些音乐吧!

首先,我们创建音乐盒。在此示例中,输入将为CDAG.DAG

的长度CDAG.DAG为8,因此我们需要一个长度为8的音乐盒:

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

然后,我们读取输入,一次输入一个字符,并将其放置O在其相应位置。

第一个字符是C,每个音符的位置与此等效(为清楚起见,我添加了空格):

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

如果输入字符是.,则我们只打印一个空行.......

因此,这C将是第三个字符。让我们将其放在顶部的音乐盒中:

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

我们将对所有其他字符重复此过程(方括号中的文本仅是为了向您显示注释,您不应输出该注释):

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

由于音乐盒的工作方式,如果我们在输出中使用O.和以外的其他字符<insert newline here>(例如空格),则它将无法播放正确的音乐!

这是一个和弦:

(ACE)

这和弦指示我们演奏的音符ACE在同一时间。.和弦中永远不会停顿。

这是这样写的:

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.

输出上允许尾随/前导空格。

因为这是,所以最短的代码获胜!


音乐字符串可以包含()两次(例如AB(CD)E(FG):)吗?
Xcoder先生17年

@ Mr.Xcoder是的,可以。
Okx

输出可以是字符列表/数组吗?
Rod

@Rod当然,根据PPCG标准
Okx

我们是否保证不会在同一和弦中得到两个相同音符?
Business Cat

Answers:


0

,29字节

28个字节的代码,-l标志+1 。

'.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"]

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>'('会把0x防止印刷/结算o的时候i==')',就会把1x重新启用的打印/清除o
i=='.'什么都不会改变时,'.......'将被打印。
字符顺序由其ASCII码给出,其中'('<')'<'*'<'.'<'@'<'A'


哦,我错过了那条评论。nvm。
quintopia

删除逗号:['.']*7。也许这是从使用元组起的一个保留时间,这需要逗号。另外,我可能错了,但这似乎['O', '.', '.', '.', '.', '.', '.']每行输出一个数组,我不确定是否允许这样做?
价值墨水


您提到了字节更改并更改了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öda97 78 76字节

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

在线尝试!

这是一个匿名函数,可从流中读取输入。像这样使用它:main { f={...}; push("ABCD") | f() }。它使用ETHproductions的答案中的正则表达式。

取消高尔夫:

{
    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该音符是否为和弦的成员,.否则进行打印。


4

JavaScript(ES6),86 85 76字节

@Neil节省了9个字节

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包含每个非换行符的情况下(如果该行包含它,则替换为.否则)。


如果可接受尾随的换行符,则可以使用保存8个字节s=>s.replace(r=/\(\w+\)|./g,x=>`ABCDEFG\n`.replace(r,c=>x.match(c)?"O":"."))
尼尔

@Neil Wow,太神奇了:-)
ETHproductions

,现在我再次测量,应该节省10个字节……
Neil

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

测试用例


2

Ruby,78 75 71个字节

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

返回字符串数组。

脱节+说明

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

尝试x.gsub(...){l=?.*7;$&.bytes{...};l+$/}scan与交换gsub,删除map,并跳过第一个,|x|因为您可以使用它$&来访问最后一个正则表达式匹配项)来保存3个字节并返回多行字符串。($/默认情况下,还会映射到换行符。)
Value 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
}

在这里尝试!


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

我确定这里有打高尔夫球的空间,但是现在可以使用,因此以后再尝试打高尔夫球。

在线尝试!

怎么运行的

基本上,该程序的工作方式是将每个字符更改为一个数字,然后将a分配给O一行中的该位置。它映射ABCDEFG.01234569

要生成单个注释行,所有要做的就是O在相应的.s 数后放置a ,然后将行填充为7个字符长。

但是,和弦的操作有些棘手。使用类似的过程,但是必须将数字转换为增量,即和弦中的第一个音符为(任意),第二个为第一个音符之后的X位置,第三个为其后的Y位置,等等。

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

首先对和弦中的所有字符进行排序。

T`L.`d

执行从字母到数字的音译(映射)。

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

用一元表示(使用xs)替换括号内的所有数字,后跟一个空格。

\)
m¶

将所有右括号替换m为换行符。在m将用作排序为即将到来的循环的标志:

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

这是一个循环替换阶段,直到无法替换为止。它取xs 的最后两个序列,然后m从中减去第一个,然后m向后移动。m需要标记是因为它必须从右到左执行此操作。

 m?x

除去x每个序列中的第一个序列,但第一个序列除外。

T`x m(`.\O_

T通过替换x.空格O,删除m并替换字母(

至此,所有和弦的线都已创建。现在必须创建单音行。

\d
$*.O¶

将每个数字替换为多个.s,后跟an O和换行符。

¶
6$*.¶
%7>`.

通过.在右侧添加s将每行填充为长度7 。这是通过.在每行的末尾添加6 s(每行将至少有一个其他字符),然后将每行的前7个字符之后的所有字符替换为空来实现的。(由于.映射到9,因此O将在这些行上切除)



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>

您不认为引号中的输入会算作2个额外的字节吗?我可能是错的,因为在其他方面可能对此达成共识。
Okx

@Okx更新了我的字节数。不确定是否将其添加到这里,还是有点新:)
CraigR8806

0

Ruby,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)"]

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)]

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


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
    ;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.