ความสอดคล้องหรือความไม่ลงรอยกัน?


36

เมื่อได้รับชื่อโน้ตสองรายการคุณจะต้องเขียนโปรแกรมที่กำหนดว่าช่วงเวลาที่เกิดขึ้นจากบันทึกย่อสองรายการนั้นสอดคล้องกันหรือไม่สอดคล้องกัน

บทนำ

ในเพลงตะวันตกมีเพียงเสียง "แตกต่าง" เพียง 12 เดียวเท่านั้น C, C#, D, D#, E, F, F#, G, G#, A, A#, Bชื่อของพวกเขาเรียงจากต่ำสุดไปสูงสุดเหล่านี้: ลำดับนั้นเป็นวัฏจักรคือมันจะดำเนินต่อไปกับอีกCหลังจากBนั้นอย่างไม่สิ้นสุด

ระยะห่างระหว่างสองโทนสีที่เรียกว่าช่วงเวลา ช่วงเวลาใด ๆ ระหว่างสองบันทึกที่มีที่อยู่ติดกันในซีรีส์ดังกล่าวข้างต้น (เช่นC — C#หรือE — F) เรียกว่าดนตรี ช่วงเวลาระหว่างบันทึกย่อที่ห่างไกลกว่าจะถูกกำหนดเป็นจำนวนของขั้นตอน semitone ที่จำเป็นในการรับจากลำดับแรกถึงสอง (ขณะที่อาจล้อมรอบลำดับ) ตัวอย่าง: D to E= 2 semitones, C to G= 7 semitones, B to D#= 4 semitones (ซึ่งล้อมรอบลำดับ) 1

ตอนนี้ช่วงเวลาเหล่านี้จะถูกแบ่งออกเป็นสองประเภท: พยัญชนะ (ฟังดูเป็นสุขถ้าคุณเล่นโน้ตทั้งสองพร้อมกัน) และไม่สอดคล้องกัน (ไม่มาก)

มากำหนดช่วงเวลาของพยัญชนะเป็น: 0, 3, 4, 5, 7, 8 และ 9 semitones

ส่วนที่เหลือของพวกเขาจะไม่สอดคล้องกันคือ: 1, 2, 6, 10 และ 11 semitones

ความท้าทาย

เขียน "โปรแกรม" (ในความหมายทั่วไปของคำว่า: ฟังก์ชั่นก็ใช้ได้อย่างสมบูรณ์) เพื่อทำสิ่งต่อไปนี้:

  • ใช้ชื่อโน้ตสองชื่อ (สตริงจากลำดับด้านบน) เป็นอินพุต คุณอาจนำไปใช้ตามที่คุณต้องการ (จาก stdin ในฐานะที่เป็นข้อโต้แย้งคั่นด้วยสิ่งที่คุณต้องการแม้จะนำพวกเขาเป็นรายการของตัวละคร (เช่น["C","#"]) อย่างไรก็ตามคุณไม่สามารถกำหนดชื่ออื่นให้กับบันทึกย่อ (โดยเฉพาะคุณ ต้องไม่ใช้หมายเลขตั้งแต่ 0 ถึง 11 และใช้หมายเลข)

  • สำหรับคุณที่ฟังเพลงออกไปมีการบันทึกจะถูกระบุโดยไม่ต้องระดับแปดเสียง ในกรณีนี้มันไม่สำคัญว่าจะมีการเรียงลำดับใดบ้างและต่ำกว่าและสูงกว่า สุดท้ายคุณไม่จำเป็นต้องจัดการชื่อใด ๆ ที่ไม่ได้อยู่ในรายการด้านบน ไม่มีการปรับปรุงอื่น ๆ เช่นE#ไม่มีแฟลตการเปลี่ยนแปลงสองครั้งและอื่น ๆ

  • เลือกค่าสองค่าใด ๆ โปรแกรมของคุณจะต้องส่งออกหนึ่งของพวกเขาเมื่อใดก็ตามที่ช่วงเวลาที่เกิดขึ้นโดยทั้งสองโน้ตในการป้อนข้อมูลเป็นพยัญชนะและอื่น ๆ ถ้าพวกเขาไม่ได้ (อาจเป็นTrueและFalseแม้กระทั่งπและ e หากคุณต้องการ :))

  • นี่คือรหัสกอล์ฟ โปรแกรมที่สั้นที่สุดเป็นไบต์ในแต่ละภาษาชนะ มีความสุข!

ตัวอย่างและกรณีทดสอบ

Note 1    Note 2    Output    Interval [semitones]
  C          D     Dissonant   2
  A#         A#    Consonant   0
  G          D     Consonant   7 (wraparound)
  D#         A     Dissonant   6
  F          E     Dissonant   11
  A          C     Consonant   3

ฉันไม่ได้เพิ่มพวกเขามากขึ้นเพราะไม่มีคดีทุจริตโดยเฉพาะในเรื่องนี้

นี่เป็นความท้าทายครั้งแรกของฉันดังนั้นคำวิจารณ์เชิงสร้างสรรค์ใด ๆ ก็ยินดีต้อนรับอย่างอบอุ่น :—) หากคุณพบว่าคำอธิบายทางทฤษฎีเลอะเทอะอย่าลังเลที่จะถามคำถาม สุดท้ายโปรดอย่าบอกฉันว่านี่คือการล่อของนี้หรือนี้ ฉันทำให้แน่ใจว่ามันไม่ใช่ (อันหลังค่อนข้างคล้ายกัน แต่ซับซ้อนกว่าฉันคิดว่าการท้าทายที่เรียบง่ายขึ้นเล็กน้อยจะทำให้ผู้คนเข้าร่วมได้ง่ายขึ้น)


1 : ฉันพยายามทำให้คำอธิบายนี้ง่ายที่สุดเท่าที่จะทำได้ มีทฤษฎีมากขึ้นรอบระยะเวลา โปรดอย่าทุบตีฉันที่ทิ้งมันไว้

คำตอบ:


12

เยลลี่ 21 ไบต์

รับอินพุตเป็นรายการของสองสตริง ส่งคืน0สำหรับความไม่สอดคล้องกันหรือ1สำหรับพยัญชนะ

OḢ6×%21_Lµ€IA“¬ɠṘ’æ»Ḃ

ลองออนไลน์!

OḢ6×%21_Lµ€IA“¬ɠṘ’æ»Ḃ   - main link
         µ€             - for each note             e.g. ["A#", "C"]
O                       -   convert to ASCII codes  -->  [[65, 35], 67]
 Ḣ                      -   keep the first element  -->  [65, 67]
  6×                    -   multiply by 6           -->  [390, 402]
    %21                 -   modulo 21               -->  [12, 3]
       _L               -   subtract the length     -->  [12, 3] - [2, 1] = [10, 2]
           IA           - absolute difference       -->  8
             “¬ɠṘ’      - the integer 540205
                  æ»    - right-shift               -->  540205 >> 8 = 2110
                    Ḃ   - isolate the LSB           -->  2110 & 1 = 0

ทำของ

ครั้งแรกที่เราควรทราบว่าฟังก์ชั่นFที่เรากำลังมองหาการสับเปลี่ยน: สำหรับคู่ของบันทึกใด ๆ(A, B)เรามีF (A, B) = F (B, A)

เนื่องจากมีอินพุตที่เป็นไปได้ไม่มากเกินไปและมีเพียง 2 เอาต์พุตที่เป็นไปได้ที่จะจัดการดังนั้นจึงต้องหาฟังก์ชันแฮชที่ค่อนข้างง่ายHเช่นนั้น| H (A) - H (B) | สร้างช่วงของค่าที่ จำกัด และปราศจากการชนกันของคู่โน้ตที่เป็นไปได้ทั้งหมด(A, B) ที่เกี่ยวกับผลลัพธ์ที่คาดหวัง

เราจะทดสอบชุดของฟังก์ชั่นH (mul, mod)ซึ่งนิยามว่า:

H(mul, mod)(s) = ((ORD(s[0]) * mul) MOD mod) - LEN(s)

ORD(s[0])รหัส ASCII ของอักขระตัวแรกของบันทึกย่ออยู่ที่ไหนและLEN(s)เป็นความยาวของบันทึกย่อ ( 2ถ้ามี'#'และ1ถ้าไม่)

ด้านล่างนี้เป็นรุ่นที่มีความคิดเห็นของรหัส JS ที่ใช้ในการค้นหาคู่ที่ถูกต้อง(mul, mod)และ bitmasks ที่เกิดขึ้น มีวิธีแก้ปัญหาที่เป็นไปได้มากมาย แต่* 6 % 21เป็นวิธีที่สั้นที่สุดด้วยวิธีนี้


3
คุณคิดยังไงกับสิ่งเหล่านี้? .. คุณได้รับ 'อัลกอริธึม' แบบนี้ด้วยมือหรือด้วยกำลังดุร้าย? และไม่คำนึงถึงคำตอบของคำถามที่สอง: อย่างไร?! .. : S " จำนวนเต็มตามตัวอักษร 540205; เลื่อนไปทางขวาด้วย (รหัส ASCII; คูณด้วย 6; โมดูโล 21; เก็บก่อน; ลบความยาว ... ); bitwise-AND 1 " คำตอบของคุณทำให้ฉันประทับใจทุกครั้ง ..
Kevin Cruijssen

@KevinCruijssen ฉันได้เพิ่มรหัส JS ดั้งเดิมที่ใช้ในการค้นหาค่าเหล่านี้
Arnauld

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

9

APL (Dyalog) , 62 39 ไบต์

ใช้⎕IO←0; 0 คือพยัญชนะ 1 ไม่สอดคล้องกัน นำรายการของตัวอักษรโน้ตพื้นฐานเป็นอาร์กิวเมนต์ด้านซ้ายและรายการ sharps เป็นอาร์กิวเมนต์ที่ถูกต้อง

{⎕A[|-/('C D EF G A '⍳⍺)+⍵=⍕#]∊'BCGKL'}

ลองออนไลน์!

{} ฟังก์ชั่นนิรนามซึ่งเป็นอาร์กิวเมนต์ด้านซ้ายและเป็นอาร์กิวเมนต์ที่ถูกต้อง

⎕A[... ]∊'BCGKL' เป็นlphabet, ดัชนีโดยต่อไปนี้เป็นสมาชิกของสตริง?

  ⍕# จัดรูปแบบรูทเนมสเปซ (ให้อักขระคม)

  ⍵= ตัวอักษรโต้แย้งที่ถูกต้อง (นักแม่นปืน) เท่ากับหรือไม่

  (... )+ เพิ่มรายการต่อไปนี้:

   'C D EF G A '⍳⍺ ดัชนีของตัวอักษรอาร์กิวเมนต์ซ้ายในสตริง

  -/ ความแตกต่างระหว่างสิ่งเหล่านั้น

  | ค่าสัมบูรณ์


คุณจะเพิ่มคำอธิบายสำหรับพวกเราที่ไม่คุ้นเคยกับ APL หรือไม่?
Draconis

@Draconis เพิ่มคำอธิบายแล้ว
อดัม

9

MATL , 30 27 26 ไบต์

,j'DJEFPGIALBC'&mQs]ZP7Mdm

อินพุตโน้ตทั้งสองในบรรทัดที่ต่างกัน เอาต์พุต0สำหรับพยัญชนะ1สำหรับความไม่สอดคล้องกัน

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบทั้งหมด

คำอธิบาย

สตริง 11 อักขระ

DJEFPGIALBC

เข้ารหัสบันทึกและช่วงเวลาที่ไม่สอดคล้องกันดังต่อไปนี้

โปรแกรมจะค้นหาดัชนีที่อิงกับ 1 ของอักขระอินพุตเป็นอันดับแรกในสตริงด้านบน การป้อนข้อมูลที่ไม่คมชัดเหมือนDจะให้1, Eจะให้3, ... , จะให้C 11ตัวเลขเหล่านี้ยังสามารถนำมาพิจารณาเป็นอาร์เรย์ตัวเลข 1 × 1 ได้อีกด้วย ข้อมูลที่คมชัดเช่นC#จะให้อาร์เรย์ 1 × 2 [11 0]ซึ่งหมายความว่าCพบที่ตำแหน่ง11และ#ไม่พบ

สังเกตว่าตัวอักษรJPILจะไม่มีอยู่ในอินพุต สำหรับตอนนี้พวกเขาจะใช้เป็นตัวยึดเพื่อให้ตัวอย่างเช่นบันทึกEเป็นสอง semitones Dดังกล่าวข้างต้น แต่จะมีประโยชน์ในการกำหนดช่วงเวลาที่ไม่สอดคล้องกัน

ตัวเลขในรายการแรกของอาร์เรย์ 1 × 1 หรือ 1 × 2 สอดคล้องกับระยะห่างระหว่างโน้ตในครึ่งวงกลม แต่ไม่นับสัญลักษณ์คม (ยัง) สังเกตว่าขนาดที่กำหนดโดยตัวเลขเหล่านี้ไม่ได้เริ่มต้นที่C; แต่นั่นไม่สำคัญเพราะเราต้องการแค่ช่วงเวลานั่นคือความแตกต่างระหว่างบันทึก การลบจำนวนที่ได้รับจะให้ช่วงเวลาหรือ 12 ลบด้วยช่วงเวลา แต่ก่อนอื่นเราต้องพิจารณาสัญลักษณ์ที่คมชัด

ในการพิจารณาโน้ตที่คมชัดวิธี golfy (ใน MATL) คือการเพิ่ม1แต่ละรายการของอาร์เรย์ 1 × 1 หรือ 1 × 2 ที่ได้รับก่อนหน้านี้แล้วรวมอาร์เรย์ (2 ไบต์) บันทึกดังนั้นไม่ใช่คมจะเพิ่มขึ้นและบันทึกโดยคมชัด1 2สิ่งนี้ทำให้โน้ตที่คมชัด 1 semitone สูงกว่าโน้ตที่ไม่คมตามที่ต้องการ เรากำลังเพิ่มเซมิโคลนพิเศษให้กับโน้ตทั้งหมด แต่นั่นไม่ได้เปลี่ยนช่วงเวลาระหว่างโน้ตเหล่านั้น ดังนั้นตอนนี้โน้ตDจะให้หมายเลขสนาม2, D#จะให้3, ... , Cจะให้12, จะให้C#13

ช่วงเวลาที่ไม่ลงรอยกันอยู่1, 2, 6, หรือ10 11สิ่งเหล่านี้มีความสมมาตรแบบโมดูโล -12 : ช่วงเวลาระหว่างสองโน้ตนั้นไม่สอดคล้องกันถ้าหากช่วงเวลาที่มีโน้ตในลำดับย้อนกลับโมดูโล 12 นั้นไม่สอดคล้องกัน

ถ้าเราคำนวณความแตกต่างของสตริง'DJEFPGIALBC'เราจะได้เวกเตอร์เป็นตัวเลข

6 -5 1 10 -9 2 -8 11 -10 1

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

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


2
ฉันชอบวิธีที่คุณเข้ารหัสโน้ตและช่วงเวลาที่ไม่สอดคล้องกันในสตริงเดียวกัน
celtschk

8

JavaScript (ES6), 68 64 ไบต์

(a)(b)จดบันทึกเป็นสองสายในไวยากรณ์ความดีความชอบ ส่งคืน0สำหรับความไม่สอดคล้องกันหรือ1สำหรับพยัญชนะ

a=>b=>488055>>(g=s=>'C D EF G A'.search(s[0])-!s[1])(a)-g(b)+9&1

กรณีทดสอบ

จัดรูปแบบและแสดงความคิดเห็น

a => b =>                       // given the two notes 'a' and 'b'
  488055 >>                     // 19-bit lookup bitmask: 1110111001001110111
    (g = s =>                   // we use g() to convert a note 's' into a semitone index
      'C D EF G A'.search(s[0]) // position of the note: -1 for 'B' (not found) to 9 for 'A'
      - !s[1]                   // subtract 1 semitone if the '#' is not there
    )(a)                        // compute the result for 'a'  --> [ -2 ...  9]
    - g(b)                      // subtract the result for 'b' --> [-11 ... 11]
    + 9                         // add 9                       --> [ -2 ... 20]
  & 1                           // test the bitmask at this position (0 if negative or > 18)

7

เยลลี่ 26 ไบต์

i@€ØAo.SḤ’d5ḅ4µ€ạ/“¢£©½¿‘ċ

ลิงก์ monadic ที่ใช้รายการของโน้ตสองรายการ (เป็นรายการของอักขระ) และส่งคืน0สำหรับพยัญชนะและ1ไม่สอดคล้องกัน

ลองออนไลน์! หรือดูปัจจัยการผลิตทั้งหมดในการทดสอบในตัว

อย่างไร?

i@€ØAo.SḤ’d5ḅ4µ€ạ/“¢£©½¿‘ċ - Link: list of lists of characters, notes
              µ€           - for €ach note in notes: (call the resulting list x)
   ØA                      -   yield the uppercase alphabet
i@€                        -   first index of c in ^ for €ach character, c
                           -     ...note '#' is not there so yields 0 (A->1, B->2,...)
      .                    -   literal one half
     o                     -   or (vectorised)  - e.g. "C#" -> [3, 0] -> [3, 0.5]
       S                   -   sum
        Ḥ                  -   double - that is ...  C C#  D D#  E  F F#  G G#  A A#  B
                                                 ->  6  7  8  9 10 12 13 14 15  2  3  4
         ’                 -   decrement         ->  5  6  7  8  9 11 12 13 14  1  2  3
           5               -   literal five
          d                -   divmod                (e.g. 9 -> [1,4] or 11 -> [2,1])
             4             -   literal four
            ḅ              -   convert from base     (e.g. [1,4] -> 8 or [2,1] -> 9)
                                                 ->  4  5  6  7  8  9 10 11 12  1  2  3
                 /         - reduce x with:
                ạ          -   absolute difference   (e.g. ["G#", "A"] -> [12, 1] -> 11)
                  “¢£©½¿‘  - code-page indices = [1, 2, 6, 10, 11]
                         ċ - count occurrences (1 if in the list, 0 if not)

5

เยลลี่ 31 ไบต์

O_65ị“¢[ḋṃ’b⁴¤+L$€Ḣ€ạ/e“cṾ’b12¤

ลองออนไลน์!

wheeeeee 32 ไบต์ยาวเกินไป

คำอธิบาย

O_65ị“¢[ḋṃ’b⁴¤+L$€Ḣ€ạ/e“cṾ’b12¤  Main link
O                                Cast each character to an int using Python `ord`
 _65                             Subtract 65 (A is 0, G is 7)
     “¢[ḋṃ’b⁴¤                   [2, 3, 5, 7, 9, 10, 0]
     “¢[ḋṃ’                      37058720
           b                     Digits in base
            ⁴                    16
    ị                            Index into this list; this creates the gaps for sharps
                 €               For each sublist
              +L$                Add the length to each element (Sharpens sharp notes)
              +                  Add
               L                 Length
                   €             For each sublist
                  Ḣ              Take the first element
                    ạ/           Absolute difference between the two (unoctaved) pitches # It's convenient that every interval's inverse (?) has the same consonance/dissonance
                      e          Is the semitone difference in
                       “cṾ’b12¤  [1, 2, 6, 10, 11]?
                       “cṾ’      25178
                           b     base
                            12   12

เฮ้นั่นเป็นคำตอบที่ยอดเยี่ยม! ฉันสงสัยว่ามีคนใช้ประโยชน์จากสมมาตรหรือไม่และคุณก็ทำได้ และฉันชอบวิธีการของคุณในการจับคู่ชื่อโน้ตกับตัวเลขด้วย! +1
Ramillies

ความแตกต่าง semitone อาจสมมาตร แต่คุณยังคงได้รับผลดัฟฟ์ - ตัวอย่าง"G#", "A"(ไม่สอดคล้องกัน) ให้ผลต่าง11ที่ไม่ได้อยู่ใน[1,2,6]นั้น
Jonathan Allan

@JanathanAllan oh uh ดีที่น่าอาย; ฉันคิดว่าความแตกต่างที่แน่นอนได้แก้ไขแล้วว่า ... ._ จะแก้ไข lol
HyperNeutrino

1
@JonathanAllan แก้ไขให้เหลือสองสามไบต์พิเศษ (3 IIRC)
HyperNeutrino

4

Mathematica, 55 ไบต์

function                                                  arguments        bytes

FreeQ[1|2|6|10|11]@Abs[#-#2&@@Sound`PitchToNumber/@#]&    [{"C","F#"}]     55

แม็พบิวด์อินภายในSound`PitchToNumberบนอินพุต (รายการของสองสตริง) รับความแตกต่างแบบสัมบูรณ์จากนั้นจับคู่รูปแบบสำหรับหมายเลขช่วงเวลาที่ไม่สอดคล้องกัน


เพื่อความสนุก (ไม่ใช่การแข่งขัน)

นี่คือบางฟังก์ชั่นที่สั้นกว่าซึ่งละเมิดข้อ จำกัด “ คุณไม่สามารถกำหนดชื่ออื่นให้กับโน้ตได้” แพ็คเกจพื้นฐานMusic`มีค่าคงที่ของโน้ตที่กำหนดไว้ล่วงหน้า (เช่นA4 = 440.) และฟังก์ชันHertzToCents(ซึ่งสามารถเล่นกอล์ฟได้) แทนที่จะเป็นสตริงเราจะใช้ค่าคงที่บันทึกย่อเป็นอาร์กิวเมนต์ แต่กำหนดในรูปแบบที่แตกต่างกันสำหรับแต่ละฟังก์ชัน

FreeQ[1|2|6|10|11]@Abs@@Round[.01HertzToCents@#]&         [{C3,Fsharp3}]   50+9=59
FreeQ[1|2|6|10|11]@Abs@Round[17Log[#2/#]]&                [C3,Fsharp3]     43+9=52
FreeQ[1|2|6|10|11]@Abs@Round[17Log@#]&                    [C3/Fsharp3]     39+9=48

การนำเข้าแพคเกจ<<Music`;ใช้เวลา 9 ไบต์

ฟังก์ชั่นนี้จะแปลงสตริง (เหมือน"F#") เป็นค่าคงที่โน้ต (เช่นFsharp3):

Symbol[StringReplace[#,"#"->"sharp"]<>"3"]&                                44

ที่จะยอมรับช่วงเวลาที่มีขนาดใหญ่กว่าคู่แทนที่ด้วยAbs[…]Mod[…,12]


เหตุใดบางช่วงจึงถือว่าไม่สอดคล้องกัน ช่วงเวลาคืออัตราส่วนของสองความถี่ หากอัตราส่วนมีตัวเศษและส่วน "ง่าย" ก็มีแนวโน้มที่จะมีความสอดคล้องกันมากขึ้น ในการปรับแต่งแบบ 5 ขีด จำกัดอัตราส่วนสามารถรวมเข้าด้วยกันเป็นพลังจำนวนเต็มของจำนวนเฉพาะน้อยกว่าหรือเท่ากับ 5 ไม่มีช่วงเวลาในอารมณ์เท่ากันนอกเหนือจากระดับแปดเสียงเป็นช่วงเวลาเพียง ; พวกเขาเป็นเพียงการประมาณที่ใกล้เคียงโดยใช้พลังของรากที่ 12 ของ 2

แทนการเข้ารหัสแบบยากซึ่งหมายเลขช่วงเวลาไม่สอดคล้องกันเราสามารถหาการประมาณค่าแบบเหตุผลของช่วงเวลาและตัดสินว่าตัวเศษและส่วนนั้นเป็น "ง่าย" หรือไม่ (หมายถึงตัวหารน้อยกว่า 5 และอัตราส่วนไม่หาร 7)

ตารางนี้แสดงแต่ละขั้นตอนในกระบวนการนั้น

Table[
  Module[{compoundInterval,simpleInterval,rationalApprox,denomLeq5,div7,consonant},
    compoundInterval = Power[2, i/12];
    simpleInterval   = 2^Mod[Log2[compoundInterval], 1];
    rationalApprox   = Rationalize[N@simpleInterval, 1/17];
    denomLeq5        = Denominator[rationalApprox]<=5;
    div7             = Denominator[rationalApprox]>1 && rationalApprox\[Divides]7;
    consonant        = FreeQ[1|2|6|10|11][Mod[i,12]];

    InputForm/@{
      i, simpleInterval, rationalApprox, 
      denomLeq5, div7, denomLeq5 && !div7,
      consonant
    }
  ], {i, 0, 12}
]

i   sInterval  ratio   denomLeq5  div7       den&&!div  | consonant?

0   1          1       True       False      True       | True
1   2^(1/12)   17/16   False      False      False      | False
2   2^(1/6)    9/8     False      False      False      | False
3   2^(1/4)    6/5     True       False      True       | True
4   2^(1/3)    5/4     True       False      True       | True
5   2^(5/12)   4/3     True       False      True       | True
6   Sqrt[2]    7/5     True       True       False      | False
7   2^(7/12)   3/2     True       False      True       | True
8   2^(2/3)    8/5     True       False      True       | True
9   2^(3/4)    5/3     True       False      True       | True
10  2^(5/6)    7/4     True       True       False      | False
11  2^(11/12)  11/6    False      False      False      | False
12  1          1       True       False      True       | True

การประมาณแบบมีเหตุผลอยู่ภายใน1/17ช่วงเวลาเนื่องจากเป็นขีด จำกัด ที่ใหญ่ที่สุดที่แยกความแตกต่างระหว่างช่วงเวลาอารมณ์แปรผันทั้ง 12 ช่วง เราให้ตรงกับตัวเลขเหตุผลที่มีรูปแบบRational[a_,b_](หรือเพียงแค่a_~_~b_) _ก่อนแล้วจึงตรงกับจำนวนเต็มมีเพียง

สิ่งนี้จะเกิดขึ้นในฟังก์ชั่นที่ค่อนข้างสั้นดังต่อไปนี้ซึ่งกำหนดว่าอัตราส่วนความถี่โดยพลการ (มากกว่า 1) เป็นพยัญชนะหรือไม่สอดคล้องกัน

Rationalize[#,1/17]/.{a_~_~b_:>b<=5&&!a∣7,_->True}&       [Fsharp3/C3]     51+9=60

1
อ๊ะอย่าบอกฉันว่า Mathematica มีสิ่งปลูกสร้างถึงแม้จะเป็นแบบนี้ ... : D
Ramillies

3

Mathematica, 118 ไบต์

FreeQ[{1,2,6,10,11},Min@Mod[Differences[Min@Position["C|C#|D|D#|E|F|F#|G|G#|A|A#|B"~StringSplit~"|",#]&/@{#,#2}],12]]&


แบบฟอร์มการป้อนข้อมูล

[ "A #", "D"]

เอาท์พุท

True->Consonant  
False->Dissonant   

ขอบคุณ @JonathanFrech -16 ไบต์


เพียงหมายเหตุ: คุณไม่จำเป็นต้องสตริงการส่งออกและConsonant Dissonantคุณสามารถส่งออกสองค่าใด ๆ แทนพวกเขา (0/1, ... อะไรก็ตาม) ที่สามารถบันทึกบางไบต์
Ramillies

1
คุณไม่สามารถละเว้นIf[...,0,1]และกำหนดได้True->Consonant; False->Dissonantหรือไม่
Jonathan Frech

1
StringCases["CC#DD#EFF#GG#AA#B",_~~"#"...]- 42 ไบต์
celtschk

1
นอกจากนี้ยังสามารถบันทึก 2 ไบต์ด้วยการแทนที่{1,2,6,10,11}ด้วย1|2|6|10|11
celtschk

1
@Skyler ดูคำตอบด้านล่าง
hftf

3

ถ่าน 30 ไบต์

≔B#A#G#FE#D#C槔o∧⌈ς”⁻⌕ζ⮌θ⌕ζ⮌η

ลองออนไลน์! การเชื่อมโยงคือการใช้รหัสเวอร์ชันอย่างละเอียด เอาต์พุต 1 สำหรับพยัญชนะ 0 สำหรับการไม่สอดคล้องกัน คำอธิบาย:

≔B#A#G#FE#D#Cζ                  Store reversed note names in z
                        θ       First input
                       ⮌        Reversed
                     ⌕ζ         Find index in z
                            η   Second input
                           ⮌    Reversed
                         ⌕ζ     Find index in z
                     ⁻          Subtract
               ”o∧⌈ς”           Compressed string 100111011100
              §                 Circularly index
                                Implicitly print

จากความอยากรู้มีเหตุผลช่วยในการจำสัญลักษณ์ที่⌕ζใช้สำหรับ "ค้นหาดัชนี" หรือไม่?
โยนาห์

@Jonah ζเป็นตัวแปรที่กำหนดให้ก่อนหน้านี้
Neil

2

J, 68 ไบต์

[:e.&1 2 6 10 11[:(12| -~/)(<;._1',C,C#,D,D#,E,F,F#,G,G#,A,A#,B')i.]

คำอธิบาย

การใช้งานที่ไม่ซับซ้อนใน J:

  • การป้อนข้อมูลจะได้รับเป็นบันทึกย่อแยกกล่อง (ผลิตโดยใช้ตัด) ในการสั่งซื้อ

  • ค้นหาดัชนีของพวกเขาในช่วงของบันทึกย่อ: (<;._1',C,C#,D,D#,E,F,F#,G,G#,A,A#,B')i.]

  • ลบแรกจากที่สอง: -~/

  • นำส่วนที่เหลือเมื่อหารด้วย 12: 12|

  • ตรวจสอบว่าเป็นหนึ่งในบันทึกที่ไม่สอดคล้องกัน: e.&1 2 6 10 11

ลองออนไลน์!


2

/// , 90 88 ไบต์

/^/"\///^\/\///C^D/##"E/DD"F/E#"G/FD"A/GD"B/AD"#,#/,"B#^B/#"A#/#"A^G#^G^F#/#"F^E^D#^D/#/

ลองออนไลน์! (กรณีทดสอบทั้งหมดในครั้งเดียว)

  • ใส่อินพุตหลังรหัส
  • แยกชื่อบันทึกย่อด้วย,B#ในแต่ละกรณีทดสอบ
  • เอาท์พุท,สำหรับพยัญชนะ,#สำหรับไม่สอดคล้องกัน
  • รองรับการเปลี่ยนแปลงสองครั้ง ( ##) หรือE#ในบางกรณี มิฉะนั้นเอาต์พุต,สำหรับพยัญชนะ#,สำหรับความไม่สอดคล้องกัน (ขอบคุณโมดูโล 12 สมมาตร)
  • สามารถจัดการกรณีทดสอบหลายรายการพร้อมกัน (ถ้าแยกออกจากกันอย่างสมเหตุสมผล)
  • อักขระตัวพิมพ์เล็กจะถูกพิมพ์ทุกประการ

2

C (gcc) , 91 ไบต์

g(char*s){return (s[1]&1|2**s&15)*4/5;}f(char*x,char*y){return (1952220<<g(x)>>g(y))&2048;}

โทร: f("A#", "D")

ค่าส่งคืน:

  • พยัญชนะ: 2048
  • Dissonant: 0

โบนัส: ฟังก์ชั่นไม่คำนึงถึงขนาดตัวพิมพ์

ลองออนไลน์!


ทั้งสองมีช่องว่างที่ไม่จำเป็นreturn (หรือไม่?
Jonathan Frech

คุณอาจลองg(char*s){s=(s[1]&1|2**s&15)*4/5;}f(char*x,char*y){x=1952220<<g(x)>>g(y)&2048;}และทางออกที่ดี!
Keyu Gan

1

Python 2, 125 117 83 78 77 ไบต์

a,b=map("C C#D D#E F F#G G#A A#B".index,input())
print chr(abs(a-b))in""

ที่""ในตอนท้ายจริงมีตัวละคร"\x02\x04\x0c\x14\x16"

ลองออนไลน์!

(+3 เพราะฉันลืม 11 หรือ 22 ในรายการเพื่อเริ่มต้นด้วย)

-8 ไบต์จากโจนาธาน Frech และเปลี่ยนไปใช้งูหลาม2

-34 ไบต์พร้อมคำแนะนำจาก Jonathan Frech และการใช้strดัชนีแทนการlistใช้

-4 ไบต์จากอินไลน์iและ Neil กลับคำแนะนำสตริง (เพียง -2 จริง ๆ เพราะฉันลืม()เครื่องกำเนิดไฟฟ้า)

-5 ไบต์จากการยกเลิกการอินไลน์i& เปลี่ยนรูปแบบอินพุต

-1 ไบต์จาก Jonathan Frech ด้วยmap()และ unprintables

รับอินพุตในหนึ่งบรรทัดของ stdin ในรูปแบบ:

'C','C#'

Trueไม่สอดคล้องกันFalseคือพยัญชนะ

คำอธิบายเก่า:

i='C C#D D#E F F#G G#A A#B'.index
a,b=input()
print abs(i(a)-i(b))in[2,4,12,20]

งูหลามstr.indexผลตอบแทนที่ต่ำสุด (บวก) ดัชนีเริ่มต้นของการจับคู่ย่อยดังนั้น และ"ABACABA".index("A") == 0 "ABACABA".index("BA") == 1ด้วยเหตุนี้เราจึงสามารถใส่ชื่อโน้ตที่เว้นระยะเท่ากันในสตริงและตราบใดที่ (ตัวอย่าง) Aมาก่อนA#การแชร์Aจะไม่เป็นปัญหา

i='C C#D D#E F F#G G#A A#B'.index

iตอนนี้เป็นฟังก์ชันที่ส่งคืนดัชนีใน'C C#D D#E F F#G G#A A#B'อาร์กิวเมนต์ (ชื่อโน้ต) คือซึ่งคือ 2 * (จำนวนเซมิโคลอนที่โน้ตเพิ่มขึ้นจากC)

a,b=input()

Python 2 input()นั้น (ส่วนใหญ่) เทียบเท่ากับeval(input())ใน Python3 ดังนั้นด้วยอินพุตที่ถูกต้องของรูปแบบ'C#','F'(ตัวอย่าง) a='C#'และb='F'

print abs(i(a)-i(b))in[2,4,12,20]

หากความแตกต่างระหว่างบันทึกย่อแรกและบันทึกย่อที่สองในสตริงไม่ใช่ 2, 4, 12, หรือ 20 (เนื่องจากชื่อบันทึกย่อจะแสดงด้วยอักขระ 2 ตัว) ดังนั้นช่วงเวลาไม่สอดคล้องกันให้พิมพ์ True ไม่เช่นนั้นจะสอดคล้องกัน พิมพ์เท็จ


เนื่องจากรูปแบบอินพุตไม่เข้มงวดคุณสามารถใช้eval(input())(13 ไบต์) แทนinput().split()(15 ไบต์)
Jonathan Frech




1
คุณสามารถใช้อักขระ Unicode ( ) แทนสตริง emtpy
Jonathan Frech

1

C (gcc) , 115117 120 ไบต์

g(char*a){a=*a-65+!!a[1]*(7-*a/70-*a/67);}f(x,y)char*x,*y;{x="(pP$HL<lt<X"[g(x)]*32+"=ZukW-^h1F6"[g(x)]>>g(y)&1;}

ลองออนไลน์!

ส่งคืน 1/0 สำหรับ consonat และ dissonat เป็นที่น่าสนใจเสมอที่จะทำการจัดการสตริงด้วย pure C ใช้อินพุตเป็นf("A#", "C")


0

PowerShell , 107 ไบต์

param($a,$b)[math]::abs(($x=-split'C C# D D# E F F# G G# A A# B').indexof($b)-$x.indexof($a))-in1,2,6,10,11

ลองออนไลน์!

เอาท์พุทTrueสำหรับไม่ลงรอยกันและFalseพยัญชนะ

รับอินพุต$aและ$bโน้ตสองตัวเป็นสตริง ดำเนินการการดำเนินงานในระดับที่แยกบนช่องว่างเพื่อสร้างอาร์เรย์ของบันทึกการร้านค้าที่เป็น-split $xค้นหา.indexof $bในอาร์เรย์นั้นให้ลบดัชนีของ$aแล้วนำabsค่า olute ไปใช้ ตรวจสอบว่าหมายเลขนั้นเป็น-inช่วงที่ไม่สอดคล้องกันหรือไม่



0

SQL, 582 ไบต์

ซอ Fiddle

ฉันยังมีสนามกอล์ฟที่จะทำ แต่ฉันต้องการที่จะลงที่นี่ก่อนที่จะจบลงอย่างสมบูรณ์

หากอินพุตอยู่ในรูปแบบตัวอักษรให้ใส่ตัวอักษรเหล่านั้นลงในตารางที่มีค่าไม่เป็นไรใช่ไหม

CREATE TABLE N(N char(2),v int)
Insert Into N values('A',1),('A#',2),('B',3),('C',4),('C#',5),('D',6),('D#',7),('E',8),('F',9),('F#',10),('G',11),('G#',12);
CREATE TABLE D(D char(9),v int) 
Insert Into D values('C',0),('D',1),('D',2),('C',3),('C',4),('C',5),('D',6);
CREATE FUNCTION I(@A char(2),@B char(2))
RETURNS char(9) as
BEGIN
DECLARE @E int=(SELECT v from N where n=@A),@F int=(SELECT v from N where n=@B)
DECLARE @C char(9) = (SELECT case D when 'D' then 'Dissonant' when 'C' then 'Consonant' END from D where v in(abs(@e-@f),12-abs(@e-@f)))
RETURN isnull(@C,'NotANote')
END

0

Perl 5 , 106 ไบต์

("C,C#,D,D#,E,F,F#,G,G#,A,A#,B,"x2)=~/$F[0],(.*?)$F[1],/;$r=(1+($1=~y/,//))%12;say(grep/$r/,(0,3..5,7..9))

ลองออนไลน์!

ส่งคืนค่าเท็จสำหรับความไม่สอดคล้องกันซึ่งเป็นจริงสำหรับพยัญชนะ

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