这个任务很简单:编写一个程序或函数,将所有音符列表(使用英语音符名称)从A♭输出到G♯。
所有没有名称由单个字母组成的音符(例如,音乐键盘上的黑色音符)都应打印其名称两次,一次为音符尖,一次为平面音。不能输出可以用单个字母描述的尖音或平音,例如B♯(C)或F♭(E)。
这是输出示例:
Ab, A, A#, Bb, B, C, C#, Db, D, D#, Eb, E, F, F#, Gb, G, G#
技术指标
"C "
代替输出"C"
吗?
这个任务很简单:编写一个程序或函数,将所有音符列表(使用英语音符名称)从A♭输出到G♯。
所有没有名称由单个字母组成的音符(例如,音乐键盘上的黑色音符)都应打印其名称两次,一次为音符尖,一次为平面音。不能输出可以用单个字母描述的尖音或平音,例如B♯(C)或F♭(E)。
这是输出示例:
Ab, A, A#, Bb, B, C, C#, Db, D, D#, Eb, E, F, F#, Gb, G, G#
"C "
代替输出"C"
吗?
Answers:
R1:删除了两者之间的逗号(挑战不需要)
R2:删除几个字节
('<;_#!=6Z|{8xUwvt,PrqonKmk)"FhCUTdb?`+<;:[Z7YtVU2T|/g-O+i(gJrHc#EC~B{@zZxw:tt'r5Qo"!l/K-hUfe?bP``_Lo~[}|X2VCTR3Q+N`_^9+7Hji3ffdAc~w|u;]\wpon4VUSSQ.PONcb(JI^]#DCYX|@?>=<:u9NMRKo32MFj.C,Ae)>'<%:^"!~5:3WxwwuRts0q(Lnml)"Fhgfe"y?a`_zyxq7YXWlUj0RgfkjMb(JI^c\[Z~BAV?T=Rv987Mq44310FEi-,G@)>b&%#"8=6Z{{yyw/Sut1*)('Km$k(!Efe{zyx>`uz]r8ZXnm3TTih.PkNchg`&HFF[DY}Az
例程在R4中获取输出指针并在其中写入注释,并用空格分隔。在示例代码中,我们直接写入屏幕。
275 001 2BD 03C 048 1DB 2B8 012 044 2A9 2BA 108 078 201 003 262
261 263 2FA 008 37A 140 225 00B 089 22C 011 2B7 018 210 000
ROMW 10 ; use 10-bit ROM width
ORG $4800 ; map this program at $4800
;; ------------------------------------------------------------- ;;
;; test code ;;
;; ------------------------------------------------------------- ;;
4800 SDBD ; set up an interrupt service routine
4801 MVII #isr, R0 ; to do some minimal STIC initialization
4804 MVO R0, $100
4806 SWAP R0
4807 MVO R0, $101
4809 EIS ; enable interrupts
480A MVII #$200, R4 ; R4 = backtab pointer
480C CALL notes ; invoke our routine
480F DECR R7 ; loop forever
;; ------------------------------------------------------------- ;;
;; ISR ;;
;; ------------------------------------------------------------- ;;
isr PROC
4810 MVO R0, $0020 ; enable display
4812 CLRR R0
4813 MVO R0, $0030 ; no horizontal delay
4815 MVO R0, $0031 ; no vertical delay
4817 MVO R0, $0032 ; no border extension
4819 MVII #$D, R0
481B MVO R0, $0028 ; light-blue background
481D MVO R0, $002C ; light-blue border
481F JR R5 ; return from ISR
ENDP
;; ------------------------------------------------------------- ;;
;; routine ;;
;; ------------------------------------------------------------- ;;
notes PROC
4820 PSHR R5 ; save return address
4821 SDBD ; R5 = pointer to @@chr
4822 MVII #@@chr, R5
4825 CLRR R3 ; R3 = 0 (space)
4826 MVII #$12, R0 ; R0 = bitmask = $12
4828 SWAP R0, 2 ; extend it to $1212
4829 @@loop MVI@ R5, R1 ; R1 = next symbol
482A MVII #('A'-32)*8, R2 ; R2 = 'A' character
482C @@note SARC R0 ; right shift the bitmask
482D BC @@next ; skip this note if the carry is set
482F MVO@ R2, R4 ; append the note
4830 MVO@ R1, R4 ; append the symbol
4831 MVO@ R3, R4 ; append a space
4832 @@next ADDI #8, R2 ; advance to the next note
4834 CMPI #('H'-32)*8, R2 ; is it now a 'H'?
4836 BLT @@note ; if not, process the inner loop
4838 TSTR R1 ; was the symbol a space?
4839 BNEQ @@loop ; if not, process the outer loop
483B PULR R7 ; return
483C @@chr DECLE ('#'-32)*8 ; '#'
483D DECLE ('b'-32)*8 ; 'b'
483E DECLE 0 ; space
ENDP
jzIntv的屏幕截图
1. CP-1610操作码使用10位值(称为“ DECLE”)进行编码。该例程的长度为31 DECLE,起始价为$ 4820,结束价为$ 483E(含税)。
print(*map(''.join,zip(3*'ADGBCEF',7*' '+5*'#b')))
Python 2:48 个字节
该代码可以调整为包括B#和Cb,而无需增加字节数。可以通过替换5
为来实现6
。
此外,它(最终)比仅输出纯字符串短:
exit('Ab A A# Bb B C C# Db D D# Eb E F F# Gb G G#')
Python 2:50 个字节
Au…b #âŽ7×bûÏ
-2个字节,感谢@maxb。
输出为列表,其中单字符注释带有尾随空格。
说明:
Au # Push the lowercase alphabet, and uppercase it
…b # # Push string "b #"
â # Take the cartesian product of both strings to create all possible pairs:
# ["Ab","A ","A#","Bb","B ","B#",...,"Zb","Z ","Z#"]
Ž7× # Push compressed integer 1999
b # Convert it to a binary string "11111001111"
û # Palindromize it to "111110011111110011111"
Ï # Only leave the notes in the list at the truthy values (1), (the trailing
# items beyond the length of this binary string are also discarded)
# (after which the result is output implicitly)
看到这个05AB1E尖矿(部分如何压缩大整数?)理解为什么Ž7×
是1999
。
Ž7×
₄·<
对于相同的字节数,也可以是(1000,double,减1)。
7£
真的有必要吗?没有它似乎运行良好。
ØAḣ7µp⁾b#Żs6ḣ€4ẎḊ;W€
单子链接,返回一个字符列表。
* 如果可接受(a)个字符列表和(b)个字符的混合列表,请删除尾随W€
18。
ØAḣ7µp⁾b#Żs6ḣ€4ẎḊ;W€ - Link: no argument
ØA - list of characters [A-Z]
ḣ7 - head to 7 "ABCDEFG"
µ - new monadic link (call that X)
⁾b# - list of characters "b#"
p - Cartesian product ["Ab","A#","Bb","B#","Cb","C#","Db","D#","Eb","E#","Fb","F#","Gb","G#"]
Ż - prepend a zero [0,"Ab","A#","Bb","B#","Cb","C#","Db","D#","Eb","E#","Fb","F#","Gb","G#"]
s6 - split into sixes [[0,"Ab","A#","Bb","B#","Cb"],["C#","Db","D#","Eb","E#","Fb"],["F#","Gb","G#"]]
ḣ€4 - head each to 4 [[0,"Ab","A#","Bb"],["C#","Db","D#","Eb"],["F#","Gb","G#"]]
Ẏ - tighten [0,"Ab","A#","Bb","C#","Db","D#","Eb","F#","Gb","G#"]
Ḋ - dequeue ["Ab","A#","Bb","C#","Db","D#","Eb","F#","Gb","G#"]
W€ - wrap each (of X) ["A","B","C","D","E","F","G"]
; - concatenate ["Ab","A#","Bb","C#","Db","D#","Eb","F#","Gb","G#","A","B","C","D","E","F","G"]
bytes
页眉中的单词链接的代码页。
ABCDEFG
.
$&b $& $&#
[BE]#...
在线尝试!说明:
ABCDEFG
插入基本注释名称。
.
$&b $& $&#
展开每个音符以包括平坦和清晰的版本。
[BE]#...
删除B#
,E#
以及它们后面的注释(Cb
和Eb
)。
Φ⪪⭆…α⁷⭆b #⁺ι벧↨⊖⊘φ²κ
在线尝试!链接是详细版本的代码。说明:
α Predefined variable uppercase alphabet
… ⁷ First 7 letters i.e. `ABCEDFG`
⭆ Map over characters and join
b # Literal string `b #`
⭆ Map over characters and join
⁺ιλ Concatenate outer and inner characters
⪪ ² Split back into substrings of length 2
Φ Filter where nonzero
φ Predefined variable 1000
⊘ Halved i.e. 500
⊖ Decremented i.e 499
↨ ² Converted to base 2 i.e. [1, 1, 1, 1, 1, 0, 0, 1, 1]
§ κ Cyclically indexed by outer index
Implicitly print matching values on separate lines
;B¯7
ï"b #" fÏÄ %9%8<6
;B Alphabet
¯7 First seven characters ("ABCDEFG")
Assign to U
ï"b #" Cartesian product with "b #" ("Ab,A ,A#,Bb,B ,B#,Cb,C ,C#,Db,D ,D#,Eb,E ,E#,Fb,F ,F#,Gb,G ,G#")
f Filter:
ÏÄ Is index + 1
%9%8 Mod 9 Mod 8
<6 Less than 6
End filter ("Ab,A ,A#,Bb,B ,C ,C#,Db,D ,D#,Eb,E ,F ,F#,Gb,G ,G#")
<6
但<5
在解释中。
p (2..18).map{|i|"FCGDAEB"[i%7]+"b #"[i/7]}
在此范围内,0..20
将打印一个包含所有平底,所有自然线和所有锐角的数组。Fb Cb E# B#
通过使用范围可以忽略不想要的2..18
注释按以下顺序打印输出 https://en.wikipedia.org/wiki/Circle_of_fifths的,或者每次以7个半音(几乎是1.5的频率比)递增。
这导致给出了音符字母顺序,其中每个音符都比上一个音符高5度(包括5度)(称为“五度”)。例如F->C
是FGABC
<<<${${(F):-{A..G}{b,,#}}//[BE]#???}
一个较丑陋的解决方案,但它节省了两个字符。(F)
在换行符上加入一个列表,并//[BE]#???
删除我们需要的字符串部分。
<<<${${:-{A..G}{b,,#}}:#([BE]#|[CF]b)}
当Zsh击败Perl时,我总是喜欢它(希望我不会太早发言...)。
<<<${${:-{A..G}{b,,#}}:#([BE]#|[CF]b)}
${:- } # empty-fallback, basically an anonymous parameter expansion
{A..G}{b,,#} # Cross product range A-G with b,(nothing),#
${ :# } # Remove matching elements
([BE]#|[CF]b) # B#, E#, Cb, Fb
<<< # Print to stdout
s<R7c.>*<r1G7"b #"2 9
s<R7c.>*<r1G7"b #"2 9 Implicit: G=lowercase alphabet
r1G Convert G to upper case
< 7 First 7 characters
* "b #" Cartesian product with "b #"
.> 2 Rotate the above 2 places to the right
c 9 Chop into pieces of length 9
<R7 Trim each to length 7
s Flatten, implicit print
编辑:部分重写以保存2字节,先前版本:s%2c*<r1G7"b #"xLG"fhoq
在线尝试!
2↓(,¨⎕A)⎕R', &'⊢'AbAA#BbBCC#DbDD#EbEFF#GbGG#'
简单的⎕R
eplace操作,,
在字符串中与字母字母中的每个字母匹配的每个元素⎕A
之前,然后删除前2个字符,
。
_=>[...'ABCDEFG'].map((n,i)=>`${i%3!=2?n+'b,':''}${n}${i%3!=1?`,${n}#`:''}`).join`,`
仅返回字符串(如下所示)将缩短36个字节,但是这样做的乐趣何在?
_=>'Ab,A,A#,Bb,B,C,C#,Db,D,D#,Eb,E,F,F#,Gb,G,G#'
--[----->+<]>-----[<+>>+>+<<-]>>+<<<-[->+++<]>+++[->>>+>+<
<<<]>>>>--->+++++++[-<<<<.>.>>.<<<.>>>.<<<.>>.>.<<<+>>>>]
All notes without a name consisting of a single letter (i.e. black notes on a musical keyboard) should have their name printed twice, once as the sharp of a note, once as the flat of one. Sharp or flat notes that can be described with a single letter, like B♯ (C) or F♭ (E) should not be outputted.
这对我来说似乎很清楚,而且我在屏幕上的OP上没有看到任何编辑历史记录。
00000000: 9d5b dc6d df7f 0603 3e40 d13c cb3a 3008 .[.m....>@.<.:0.
00000010: fff5 7b2f ffaf fff1 20f1 10ec 76 ..{/.... ...v
说明:
Z80Golf只是基于Z80 8位CPU的简单幻想机器。程序在内存位置加载0x0000
,其余的内存将填充零。通过调用来完成输出0x8000
,它将输出寄存器A的值作为字符。
程序从将要处理的数据开始,总共6个字节。每对字节指定一个音符后缀,以及一个位掩码,该位掩码控制哪些字母可以与此音符组合。为了节省字节,后缀字符被反转(xor 0xff
)-这允许将数据作为指令执行而几乎没有副作用,从而可以删除跳过此数据的跳转:
; GFEDCBA
db 0xff^'b', 0b01011011 ; Ab Bb Db Eb Gb
db 0xff^'#', 0b01101101 ; A# C# D# F# G#
db 0xff^' ', 0b01111111 ; A B C D E F G
skip_data:
这是CPU解码的方式:
sbc a, l ; a subtraction with carry on registers we don't care about
ld e, e ; put the E register back into itself. This instruction is useless
; but still exists to make the encoding regular.
call c, 0xdf6d ; if the carry flag is set, call a function. The carry flag isn't set
; because of the initial register values (all zeroes) when the sbc above
; was executed
ld a, a ; as above, put A back into itself.
一次将这两个数据读入DE寄存器对。堆栈指针用于指向下一个元素。它从0开始,并且由于Z80使用完整的降序堆栈,因此所有pop都将读取下一个数据对-所有堆栈操作均为16位。
外循环通过B寄存器中的递减计数器实现,Z80为此提供了以下djnz
指令形式的特殊支持:
ld b, 3
process_pair:
...
djnz process_pair
halt
当前字母保存在A寄存器中。因为增量在循环开始时就很合适,所以我们加载的值比实际的起始值小A
:
process_pair:
ld a, 'A'-1
pop de ; D = bitmask, E = suffix character
process_note:
inc a
srl d ; put the current bitmask bit in the carry flag
; also sets the zero flag if this is the last note in the pair
jr nc, skip
; Print the note. Note that we need to preserve the zero flag to check it in the
; loop condition later.
rst $38 ; Short encoding of call $0038.
; Because the program is so short, the memory in the 0038..8000 range
; is filled with zeroes, which happens to be the encoding for a no-op.
; The execution will therefore fall-through to the character-print hook.
push af ; Save the letter on the stack (which will be just to the left of the
; unprocessed data) to free up A for printing other characters.
; (only 16-bit register pairs can be saved, so we also push the flags)
ld a, e
cpl ; Undo the inversion used to make the execution fall-through the data.
; Done again each iteration because it takes less bytes to operate
; on the A register.
rst $38 ; Print the suffix.
xor a ; Standard assembly practice of setting a register to zero by XORing it
; with itself. Saves a byte over a simple `ld a, 0`.
rst $38 ; Print a null byte as a separator.
pop af ; Restore the current letter from the stack.
skip:
jr nz, process_note ; If the zero flag (last changed at the srl d) is not set,
; loop once again
djnz process_pair
halt