จัดระเบียบเพลงของโบสถ์เกรโกเรียน


19

ปีคือ 930 และโบสถ์เกรโกเรียนกำลังมีปัญหา พวกเขามีเพลงสวดมนต์หลายพันหน้า แต่ปัญหาก็คือแผ่นเพลงทั้งหมดถูกโยนลงกองแทนที่จะเป็นระบบองค์กรจริง:

ภาพแผ่นเพลง
ภาพโดย gamerprinter ผู้ใช้ที่สมาคม cartographers'

คริสตจักรจำเป็นต้องจัดระเบียบแผ่นเพลงทั้งหมดดังนั้นพวกเขาจึงว่าจ้างวิศวกรซอฟต์แวร์ยุคกลางเพื่อเขียนโปรแกรมเพื่อจัดระเบียบให้พวกเขา คุณเป็นวิศวกรซอฟต์แวร์ที่ได้รับการว่าจ้าง อย่างไรก็ตามกระบวนการรวบรวมในยุคกลางนั้นเกี่ยวข้องกับโปรแกรมที่เขียนลงบนกระดาษโดยทีมงานของนักเขียนพระคัมภีร์ช้า ในการลดเวลาที่ใช้ในการรวบรวมโค้ดของทีมคุณต้องทำให้โปรแกรมมีขนาดเล็กที่สุดเท่าที่จะทำได้

คริสตจักรต้องการเพลงสวดมนต์ที่จะจัดตามออกขนาดดนตรีที่พวกเขาจะถูกเขียนใน. ทั้งหมดของเพลงสวดมนต์ในโบสถ์ถูกเขียนในเครื่องชั่ง Dorian เมื่อได้รับโน้ตของดนตรีชิ้นหนึ่งโปรแกรมของคุณจะส่งออกมาตราส่วนของโดเรียนที่มีอยู่ในที่นี่ฉันจะอธิบายอย่างชัดเจนว่ามาตราส่วนของโดเรียนคืออะไร หากคุณรู้อยู่แล้วคุณสามารถข้ามส่วนนี้ได้

มี 12 โน้ตที่เป็นไปได้ในทำนองใด ๆ ที่นี่พวกเขาอยู่ในลำดับ:

C C# D D# E F F# G G# A A# B

ดนตรี (แสดงโดยใช้S) เป็นขั้นตอนที่เพิ่มขึ้นไปทางขวาหนึ่งห่อรอบ (ดังนั้นดนตรีขึ้นมาจาก B จะกลับไปที่ C) เสียง (แสดงโดยใช้T) เป็นสอง semitones ตัวอย่างเช่น semitone ที่เพิ่มขึ้นจาก F # จะเป็น G เสียงที่เพิ่มขึ้นจาก F # จะเป็น G #

ในการสร้างมาตราส่วนของโดเรียนเราเริ่มจากโน้ตใด ๆ ในรายการจากนั้นเลื่อนขึ้นในรูปแบบต่อไปนี้โดยเขียนรายการโน้ตที่เราพบ:

T, S, T, T, T, S

ตัวอย่าง. ฉันเริ่มต้นจาก A. บันทึกในระดับ Dorian ของฉันจะกลายเป็น:

A
B  (up a tone)
C  (up a semitone)
D  (up a tone)
E  (up a tone)
F# (up a tone)
G  (up a semitone)

ขนาดมีบันทึก A, B, C, D, E, F # และกรัมเพราะผมเริ่มต้นจากการที่เราจะเรียกสิ่งนี้ว่าขนาด Dorian ใน บริษัท A ดังนั้นจึงมีเครื่องชั่ง Dorian ถึง 12 เครื่องซึ่งแต่ละเครื่องมีการตั้งชื่อตามบันทึกย่อที่เริ่มต้น แต่ละคนใช้รูปแบบของเสียงและเซมิโคลอนเดียวกันโดยเริ่มจากตำแหน่งที่แตกต่างกัน หากคำอธิบายของฉันไม่ได้เชื่อมโยงกันคุณอาจปรึกษาวิกิพีเดีย

สามารถป้อนอินพุตของโปรแกรมจากสิ่งที่เหมาะสมสำหรับโปรแกรมของคุณ (เช่น STDIN, อาร์กิวเมนต์บรรทัดคำสั่ง, raw_input()) มันอาจไม่ได้เริ่มต้นล่วงหน้าในตัวแปร การป้อนข้อมูลจะเป็นรายการของบันทึกย่อคั่นด้วยเครื่องหมายจุลภาคแสดงถึงทำนองของชิ้นส่วน อาจมีการบันทึกซ้ำ จะมีบันทึกที่แตกต่างกันมากพอในอินพุตเพื่อให้สามารถอนุมานขนาดของชิ้นได้อย่างเด็ดขาด ตัวอย่างอินพุต:

B,B,D,E,D,B,A,G#,A,G#,E,D,F#,E,F#,E,F#,G#,A

เอาต์พุตของโปรแกรมควรเป็นสตริงDorian scale in Xโดยที่ X คือบันทึกย่อเริ่มต้นของสเกล ผลลัพธ์ของอินพุตตัวอย่าง:

Dorian scale in B

เปรียบเทียบสิ่งนี้กับระดับ Dorian ใน B ( B C# D E F# G# A) เราเห็นว่าโน้ตทั้งหมดของทำนองนั้นอยู่ในระดับนี้ หมายเหตุ C # ไม่ได้ใช้ในกรณีนี้ อย่างไรก็ตามมีบันทึกเพียงพอที่จะระบุ B Dorian เป็นคีย์ที่ถูกต้องอย่างไม่น่าสงสัย ไม่มีมาตราส่วนของโดเรียนอื่นที่เหมาะสมเพราะไม่ว่าเราจะลองสเกลอื่นใดจะมีโน้ตอย่างน้อยหนึ่งเพลงที่ไม่ได้เป็นสเกล

นี่คือรหัสกอล์ฟดังนั้นรายการที่มีจำนวนอักขระสั้นที่สุดจะเป็นผู้ชนะ ถามในความคิดเห็นหากคุณมีคำถาม


ดังนั้นสิ่งที่เราควรทำคือการตีความเฉพาะโทนเสียง / เซมิโทนครั้งแรกเท่านั้น?
avall

@ ทั้งหมดฉันขอโทษฉันไม่เข้าใจคำถามของคุณ ข้อมูลป้อนเข้าจะไม่ขึ้นต้นด้วยยาชูกำลังทุกครั้งหากนั่นคือสิ่งที่คุณต้องการ
absinthe

โปรดให้ตัวอย่างเพิ่มเติมแก่เรา โดยเฉพาะผู้ที่ไม่ได้เริ่มต้นด้วยยาชูกำลัง
avall

1
ปัญหาผกผันคือปรับขนาดจากคีย์และโหมด
Peter Taylor

1
@ David ตามคำถามเมตานี้ฉันได้รับการยอมรับคำตอบที่สั้นที่สุดหลังจากระยะเวลารอ 12 วันนับตั้งแต่ฉันเริ่มท้าทาย มันเพิ่งเกิดขึ้นเป็นคำตอบที่ถูกโพสต์ CJam ขวาเมื่อฉันกำลังจะไปรับคนที่สั้นที่สุดต่อไป
absinthe

คำตอบ:


2

CJam - 61

C,q',/f{"FCGDAEB"_5<'#f++:s@m<7<:A-!{"Dorian scale in "A3=}*}

ลองที่http://cjam.aditsu.net/


ว้าวนี่น่าจะเป็นชัยชนะที่รวดเร็วที่สุดของฉัน .. น้อยกว่า 1 นาที :)
aditsu

8

C, 171 146

i,b;main(int c,char**v){for(;c=v[1][i];)b|=c/65<<c*2%7+v[1][++i]%2*7;for(i=12;i--;)b&(1016056>>i)||printf("Dorian scale in %c%c",65+i*3%7,(i<5)*35);}

การแยกสตริงใน C นั้นไม่ใช่เรื่องง่ายดังนั้นฉันจึงใช้วิธีการทางคณิตศาสตร์มากขึ้น

ฉันใช้ประโยชน์จาก Circle of Fifths หากเราจัดเรียงบันทึกตามลำดับต่อไปนี้โดยนับจาก 7 semitones ในแต่ละครั้ง (รู้จักกันในชื่อ "ที่ห้า") เราพบว่าบันทึกทั้งหมดที่ได้รับอนุญาตในรูปแบบที่กำหนดใด ๆ นั้นมีบล็อกต่อเนื่องกัน 7 รายการและบันทึกที่ต้องห้ามทั้งหมด รูปแบบบล็อกที่ต่อเนื่องกัน 5 โน้ต

F C G D A E B F# C# G# D# A#

(เป็นวงกลมมันวนกลับไปFที่ท้าย)

ตำแหน่งของบันทึกธรรมชาติในลำดับข้างต้นสามารถคำนวณ(ASCII code) * 2 % 7ได้ดังนี้ ถ้าอักขระถัดไปเป็นเลขคี่ (ใช้กับ#แต่ไม่ใช่เครื่องหมายจุลภาคเว้นวรรคหรือศูนย์ไบต์) เราเพิ่ม 7 เพื่อทำให้มันคมชัด เราเก็บบิตแมปของบันทึกย่อที่มีการใช้งาน

ตัวเลข243(ไบนารี11111000) สอดคล้องกับบันทึกที่ต้องห้ามในระดับ A # Dorian ฉันคูณนี้โดยให้หมายเลขมายากล(1<<12)+1=4097 1016056นี่คือสิทธิ์ในการตรวจสอบ (โดย ANDing) หากท่วงทำนองนั้นมีโน้ตที่ต้องห้ามสำหรับเครื่องชั่ง 12 เครื่องแต่ละเครื่อง หากทำนองนั้นไม่มีโน้ตต้องห้ามสเกลจะถูกพิมพ์

สำหรับการส่งออกที่เราต้องพิมพ์ชื่อขนาดเข้ารหัสในลำดับที่กลับไปยังวงจรของเศษข้างต้นจำได้ว่าเราจะย้อนกลับเพราะเรากำลัง rightshifting.) ลำดับ ASCII ถูกสร้างขึ้นโดยADGCFBEADGCF 65+i*3%7สำหรับห้าคนแรกของเหล่านี้จะต้องมีการพิมพ์ที่คมชัด

รหัสที่ไม่ได้รับการปรับปรุง

i,b;
main(int c,char**v){
  for(;c=v[1][i];)                          //for each character in first commanline argument v[1]
                                               //if it is a letter (assume uppercase, ASCII 65 or over)
   b|=c/65<<c*2%7+v[1][++i]%2*7;               //convert to position in the circle of fifths. 
                                               //Add 7 if the next character is odd (ASCII'#')
                                               //leftshift 1 by this number and OR this with the contents of b.

  for(i=12;i--;)b&(1016056>>i)||printf         //if melody includes no prohibited notes for the scale i, print
   ("Dorian scale in %c%c",65+i*3%7,(i<5)*35); //the scale letter, and a # (ASCII 35) if required, otherwise an ASCII 0.
}

พฤติกรรมการป้อนข้อมูลไม่ถูกต้อง: หากบันทึกไม่เพียงพอจะถูกส่งไปกำหนดมาตราส่วนอย่างไม่น่าสงสัยก็จะส่งออกเครื่องชั่งที่เป็นไปได้ทั้งหมด หากมีการรวมกันของบันทึกย่อที่เป็นไปไม่ได้ หมายเหตุต้องคั่นด้วยเครื่องหมายจุลภาค (หรืออักขระที่ไม่ใช่ช่องว่างอื่น ๆ ที่มีรหัส ASCII คู่ <= 64. ) ช่องว่างไม่สามารถใช้เป็นทุกอย่างหลังจากเว้นวรรคแรกจะถือว่าเป็นอาร์กิวเมนต์ที่แตกต่างกัน รหัส ASCII> 64 จะถูกตีความเป็นบันทึกในลักษณะที่อธิบายไว้


มันทำให้ฉันตกใจที่วงกลมหนึ่งในห้ามีคุณสมบัตินี้! บางทีฉันสามารถใช้มันเพื่อตีกอล์ฟอีกเล็กน้อย
เรย์

1
@ เรย์นี่เป็นเหตุผลว่าทำไมเราถึงมีโน้ตที่เรามี อ็อกเทฟมีอัตราส่วนความถี่ 2: 1 ที่ห้าตามที่กำหนดโดย Pythagoras มีอัตราส่วน 3: 2 และเป็นช่วงเวลาดนตรีที่สำคัญที่สุดหลังจากคู่ เนื่องจาก 1.5 ^ 12 อยู่ใกล้กับ แต่ไม่เท่ากับ 2 ^ 7 อารมณ์ที่เท่าเทียมกันที่ทันสมัยจะถูกบีบลงมาที่ 1.4983 เพื่อให้ 12 เศษพอดีใน 7 อ็อกเทฟ โซลูชันแบบเก่านั้นใช้เพียง 7 โน้ตจาก 12 ตัวที่มีอยู่ในแวดวงเท่านั้น นั่นเป็นเหตุผลที่เรามีสเกลบนพื้นฐานของ 7 โน้ตที่เว้นระยะไม่สม่ำเสมอ มันไม่ใช่การประชุมแบบสุ่ม แต่ก็มีคณิตศาสตร์ที่แข็งแกร่งอยู่ข้างหลัง
เลเวลริเวอร์เซนต์

มีเครื่องมือหลายอย่างที่จัดเรียงโน้ตในห้าเพื่อความสะดวก (ไวโอลินถูกปรับด้วยวิธีนี้และกีตาร์เบสปรับเป็นสี่ในสี่ซึ่งเป็นอัตราส่วน 4: 3) ตัวอย่างที่โดดเด่นที่สุด (และเครื่องมือเดียวที่ฉันรู้ที่มีบันทึกวางออกมาในวงกลมของเศษสำหรับการออกแบบอะคูสติกที่ดี) เป็น steelpan นี้: google.es/patents/US7696421 ด้วยเลย์เอาต์นี้มันไม่สำคัญว่าโน้ตที่อยู่ถัดจากอันที่คุณกดปุ่มดังขึ้นเล็กน้อย
เลเวลริเวอร์เซนต์

4

Haskell - 152

w=words
n=w"C C# D D# E F F# G G# A A# B"
f s="Dorian scale in "++[n!!i|i<-[0..11],all(`elem`[(n++n)!!(i+j)|j<-[0,2,3,5,7,9,10]])s]!!0
main=interact$f.w

Ungolfed

type Note = String
type Scale = [Note]

notes :: [Note]
notes = words "C C# D D# E F F# G G# A A# B"

isScale :: Scale -> [Note] -> Bool
isScale scale notes = all (`elem` scale) notes

takeScale :: Int -> Scale
takeScale i = [(notes ++ notes) !! (i + j) | j <- [0, 2, 3, 5, 7, 9, 10]]

findScale :: [Note] -> Note
findScale xs = head [notes !! i | i <- [0..11], isScale (takeScale i) xs]

main = interact (("Dorian scale in "++) . findScale . words)

3

Python 2 - 177 ตัวอักษร

มันไม่สั้นขนาดนั้น แต่ฉันคิดว่ามันเป็นความสนุกของ Python ที่เขียนหลายซ้อนสำหรับลูปในบรรทัดเดียวแม้ว่าจะไม่เล่นกอล์ฟ น่าเสียดายที่ฉันต้องใส่คำสั่งการป้อนข้อมูลในบรรทัดแยกต่างหากเพื่อที่จะไม่ดำเนินการมากกว่าหนึ่งครั้ง

j=set(raw_input().split(','))
print"Dorian Scale in",[x for x in[["A A# B C C# D D# E F F# G G#".split()[(b+n)%12]for n in[0,2,3,5,7,9,10]]for b in range(12)]if j<set(x)][0][0]

ฉันไม่ได้ใช้ Python 3 แต่ฉันเชื่อว่านี่เป็นอินสแตนซ์ที่หายากเมื่อคำสั่งการพิมพ์ไม่ต้องการอักขระเพิ่มเติม เนื่องจากprintเป็นฟังก์ชั่นที่นั่นผมจะสามารถชดเชยความจำเป็นในการวงเล็บกับการใช้งานของรายการเอาออกผู้ประกอบการที่จะมาแทนที่สุดท้าย*[0]


2
นอกจากนี้คุณยังจะสามารถที่จะทดแทนinputสำหรับraw_inputและบันทึก 4 ตัวอักษรในหลาม 3.
comperendinous

"ฉันคิดว่ามันเป็นความปิติยินดีของ Python ในการเขียนหลาย ๆ ซ้อนสำหรับลูปในบรรทัดเดียว": แต่คุณพบความสุขในการอ่านพวกเขา?
คาเลบพอล

@ ภาพสไลด์แน่นอนไม่ใช่ ... มันคือทั้งหมดที่เกี่ยวกับรหัสการเขียนเท่านั้น!
feersum

3

ทับทิม - 132

12.times{|i|$*[0].split(?,)-(g=(0..6).map{|j|%w{C C# D D# E F F# G G# A A# B}[-i+=~(58>>j&1)]})==[]?(puts"Dorain scale in "+g[0]):g}

อินพุตจาก args ของบรรทัดคำสั่ง
เช่นruby dorianscale.rb B,B,D,E,D,B,A,G#,A,G#,E,D,F#,E,F#,E,F#,G#,A

ลองดูได้ที่: ideone


3

Haskell - 140

ใช้ประโยชน์จากคุณสมบัติของ Circle of Fifths ที่ @steveverrill นำมาใช้ หากเราปล่อยให้circle0 = words "C G D A E B F# C# G# D# A# F"และcircle = circle0 ++ circle0จากนั้นเราสามารถสร้างเครื่องชั่งทั้งหมดโดยการจดบันทึก 7 ติดต่อกันcircleมา

scales = [take 7 . drop i $ circle | i <- [0..11]]

ในแต่ละสเกลที่สร้างโดยวิธีนี้scale !! 3องค์ประกอบที่ 4 คือชื่อสเกล

รหัส

w=words
n=w"C G D A E B F# C# G# D# A# F"
f s="Dorian scale in "++[x!!3|x<-[take 7.drop i$n++n|i<-[0..]],all(`elem`x)s]!!0
main=interact$f.w

Ungolfed

type Note = String
type Scale = [Note]

notes :: [Note]
notes = words "C G D A E B F# C# G# D# A# F"

scales :: [Scale]
scales = [take 7 . drop i $ notes ++ notes | i <- [0..11]]

findScale :: [Note] -> Note
findScale xs = head [scale !! 3 | scale <- scales, all (`elem` scale) xs]

main = interact (("Dorian scale in "++) . findScale . words)

2

สกาล่า 130 128 127

print("Dorian scale in "+(".#?".r findAllIn "FCGDAEBF#C#G#D#A#"*2 sliding(7)find{l=>args(0)split','forall(l contains _)}get 3))

ใช้วงกลมวิธีที่ห้า อินพุตจาก args ของบรรทัดคำสั่งเช่น

scala dorianscale.scala B,B,D,E,D,B,A,G#,A,G#,E,D,F#,E,F#,E,F#,G#,A
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.