เล่น“ Taps”


31

วันนี้ 11 พฤศจิกายน 2558 เป็นวันทหารผ่านศึกในสหรัฐอเมริกา " Taps " เป็นการเรียกแตรที่เล่นในงานศพของกองทัพสหรัฐฯ:

( "Taps" บน SoundCloudจากvtmiller )

มันเป็นทำนองที่เรียบง่ายโน้ตยาวยี่สิบสี่ตัวและใช้โน้ตสี่แบบที่แตกต่างกันเท่านั้น นี่คือแผ่นเพลง:

ตบแผ่นเพลง (ที่มา )

ท้าทาย

เขียนโปรแกรมหรือฟังก์ชั่นที่เล่น "Taps" หรือส่งออกไฟล์เสียงของ "Taps" ในรูปแบบไฟล์เสียงทั่วไป (เช่น MP3, WAV, MIDI) มันอาจจะเล่นในคีย์ใด ๆ โดยใช้เครื่องมือชนิดใดหรือเสียงบี๊บที่มีให้ในภาษาของคุณ ตัวอย่างเช่นมันอาจฟังดูเหมือนเปียโนแทนที่จะเป็นแตรเดี่ยว (แม้ว่าจะยังคงใช้เครื่องมือเพียงชนิดเดียวเท่านั้น)

โน้ตยี่สิบสี่ทั้งหมดจะต้องเล่นด้วยระยะห่างที่แม่นยำและระยะห่างที่ถูกต้อง คนที่คุ้นเคยกับ "Taps" ควรจะสามารถเรียกใช้รหัสของคุณและจดจำเพลงที่กำลังเล่นได้อย่างง่ายดาย

ระยะเวลาของเมโลดี้ (ตั้งแต่เริ่มต้นบันทึกย่อแรกถึงสิ้นสุดบันทึกสุดท้าย) จะต้องอยู่ระหว่าง 30 และ 70 วินาที คุณสามารถเลือกที่จะเงียบได้สูงสุด 5 วินาทีในการเริ่มต้นและ / หรือสิ้นสุดไฟล์เสียงของคุณดังนั้นไฟล์ 80 วินาทีนั้นยาวที่สุด

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

เกณฑ์การให้คะแนน

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

โปรดทราบว่าคุณสามารถฝังไฟล์เสียงSoundCloud ลงในโพสต์โดยตรงโดยวางลิงก์ในบรรทัดว่าง หากคุณมีบัญชี SoundCloud นี่จะเป็นวิธีที่ยอดเยี่ยมในการแบ่งปันผลลัพธ์ของคุณ


ฉันกำลังคิด ChucK
The_Basset_Hound

4
คาลวินถ้าคุณไม่รังเกียจฉันจะโพสต์คำตอบกอล์ฟสองสามฉบับในพื้นฐานเก่าและบริจาคให้กับองค์กรการกุศลทหารผ่านศึกนอก PPCG คุณเป็นแรงบันดาลใจให้ฉันทำอย่างนั้น BTW ในสหราชอาณาจักรเรามีวันอาทิตย์เป็นวันอาทิตย์ที่สองของเดือนพฤศจิกายนซึ่งหมายความว่าปีนี้เป็นวันอาทิตย์สุดท้าย หนึ่งในความทรงจำที่เก่าแก่ที่สุดของฉันคือยืนอยู่ข้างอนุสาวรีย์ที่ล้อมรอบด้วยดอกป๊อปปี้ซึ่งเป็นที่สังเกตของความเงียบ 2 นาที ฉันอายุประมาณ 3 ขวบเมื่อฉันถามแม่ว่าทำไมไม่มีใครพูดเธอบอกให้ฉันเงียบ
เลเวลริเวอร์เซนต์

มีกฎสำหรับความยาวของแฟร์มาสหรือไม่?
SirPython

@SirPython ฉันไม่รู้ด้วยซ้ำว่าสัญลักษณ์นั้นมีความหมายว่าอย่างไร! อ้างอิงจากen.wikipedia.org/wiki/Fermata "แน่นอนว่าจะมีการจัดขึ้นอีกนานเท่าไหร่ขึ้นอยู่กับดุลยพินิจของนักแสดง" การใช้ดุลพินิจของผลลัพธ์ไม่พอดีกับ codegolf ดังนั้นฉันจึงเล่นตามที่เขียนไว้ ฉันเห็นว่าคุณกำลังจะไปที่ใด ... การเพิ่มความยาวโน้ตที่จุดสองจุดสามารถบีบอัดโน้ตประที่แปดลงไปเป็นโน้ตที่สิบหกทำให้สิ่งต่าง ๆ ง่ายขึ้น แต่ฉันคิดว่านั่นคือการโกง :-)
ระดับแม่น้ำเซนต์

คำตอบ:


4

qb64, 100 84 ไบต์

รุ่นเก่าของ Qbasic ที่ปรับปรุงแล้วสามารถดาวน์โหลดได้ที่http://www.qb64.net/

Count ไม่รวมช่องว่างซึ่งไม่จำเป็นและมีเพียงเพื่อแยกข้อมูลออกเป็นวลีสามโน้ตเพื่อความชัดเจน

PLAY"T99L4C.L8CL1F. L4C.L8FL1A. L4CFL2A L4CFL2A L4CFL1A. L4F.L8AL1>C< L2AFL1C. L4C.L8CL1F."

คำสั่งในสตริงการเล่น

T99     set tempo to 99 quarter notes per minute (default is 120, only just too short)
CDEFGAB play notes in the current octave
><      up or down one octave
Lx      following notes are of note of 1/x duration
.       extend previous note duration by 50%

ประวัติศาสตร์การเล่นกอล์ฟ:

โพสต์แรก: 4/4 ครั้งถึง 4/2 ครั้งซึ่งหมายความว่าฉันมีบันทึกย่อทั้งหมด แต่ไม่มีโน้ตที่สิบหก

แก้ไข 1: คีย์เปลี่ยนจาก C (ช่วง GG) เป็น F (ช่วง CC) ตอนนี้ฉันต้องทำการเปลี่ยนแปลงระดับแปดเสียงเพียงครั้งเดียวสำหรับค่า C สูงซึ่งจะเกิดขึ้นเพียงครั้งเดียวแทนที่จะเป็นค่า G ต่ำทั้งหมดเหมือนเดิม

หลังจากกำจัดการเปลี่ยนแปลงระดับแปดเสียงทั้งหมดแล้วฉันไม่คิดว่าจะมีกอล์ฟอีกต่อไป มีทั้งหมด 20 Lรายการ แต่ไม่มีวิธีที่ชัดเจนในการหลีกเลี่ยง

วลีสุดท้าย (11 ตัวอักษร) เหมือนกันกับวลีแรก แต่ไม่มีวิธีที่จะแทรกสองครั้งในความยาว 11 ตัวอักษร ข้อมูลที่ทำซ้ำจะมีเพียง 9 ตัวอักษรหากการลบเริ่มต้นL4(ดูเหมือนไม่จำเป็นเนื่องจากความยาวบันทึกย่อเริ่มต้นน่าจะเป็นหมายเหตุไตรมาส แต่ไม่มีการบันทึกไว้ดังนั้นฉันจึงทิ้งไว้)


9

JavaScript, 203 198 196 195 ไบต์

with(new AudioContext)for(t=i=0;n="301093301396202346202346202396331699464390301093"[i++];)with(createOscillator())i%2?l=n/2:(frequency.value=392+n*44,connect(destination),start(t+.1),stop(t+=l))

บันทึก 5 ไบต์ด้วยDendrobiumและ 1 ขอบคุณ @PatrickRoberts

คำอธิบาย

with(new AudioContext)        // use HTML5 audio
  for(                        // iterate through the note pitches and lengths
    t=i=0;                    // t = current time to place the note
    n=                        // n = note pitch (or temporarily length)

    // This string contains the values of each note alternating between length and pitch
    //     (l1, p1, l2, p2, etc...)
    // Length value is in 16th notes (1 = 1/16th note, 2 = 1/8th, etc...)
    //     The longer notes are limited to 9 but I think it still sounds OK
    // Pitch value 0 = G4, 3 = C5, 6 = E5, 9 = G5 (multiples of 3 saves 1 byte)
    "301093301396202346202346202396331699464390301093"

  [i++];)
    with(createOscillator())  // create the note oscillator
      i%2?                    // alternate between length and pitch characters
        l=n/2                 // l = length (stored for use in the next iteration)
                              // dividing it by 2 sets the speed to 60 beats per minute
                              //     and casts it to a number
      :(
        frequency.value=392   // base note = G5 (392hz)
          +n*44,              // there is (conveniently) roughly 132hz between each note
        connect(destination), // send the note's sound through the speakers
        start(t               // schedule the note to sound
          +.1),               // short delay to distinguish two notes of the same pitch
        stop(t+=l)            // schedule the end of the note and increment the time
      )

ทดสอบที่นี่ในเบราว์เซอร์! ใช้งานบนเบราว์เซอร์ที่สนับสนุน HTML5 Web Audio API


1
-5 ไบต์: c = new AudioContext (); สำหรับ (t = i = 0; n = "30109330139620234620234620234620239620239633169946439090101093" [i ++];) ด้วย (c.createOscillator ()) i% 2? l = n / 2: (ความถี่ value = 392 + n * 44, เชื่อมต่อ (c.destination), เริ่มต้น (t + .1), หยุด (t + = l))
Dendrobium

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

@ThomasKwa ใช่มันไม่สมบูรณ์แบบ แต่ข้อกำหนดคือต้องจดจำได้ง่ายดังนั้นฉันจะบอกว่ามันผ่านไปแล้ว (ฟังเพลงใน SoundCloud ด้วยเช่นกันโน้ตครึ่งแรกที่เป็นจุดตรงคือ 10/16 ดังนั้นถ้าเราไปตามเวอร์ชั่นนั้นมันค่อนข้างใกล้!: P)
user81655

8

Mathematica, 361 287 285 ไบต์

ฉันไปเพื่อความแม่นยำที่นี่ เอาท์พุทตรงตามที่อธิบายไว้ในคะแนนเล่นกับทรัมเป็ต คุณสามารถค้นหาไฟล์ที่นี่

"G"
e="E5";c="C5";EmitSound@Sound[SoundNote[#,5/#2,"Trumpet",SoundVolume->#3/17]&@@@{%,8,17,%,24,20,c,2,23,%,8,26,c,24,29,e,2,32,%,12,35,c,12,38,e,6,41,%,12,44,c,12,47,e,6,50,%,12,53,c,12,56,e,2,59,c,8,62,e,24,65,"G5",3,68,e,6,170/3,c,6,136/3,%,2,34,%,8,34,%,24,34,c,2,34}~Partition~3]

ขอบคุณ @ MartinBüttnerสำหรับคำแนะนำการเล่นกอล์ฟ


4
ลิงก์ไม่อนุญาตให้ฉันได้ยินเพลง ดูเหมือนว่าจะถูกลบออกหรือไม่สามารถฟังได้เนื่องจากสิทธิ์
d0nut

2
เพื่อจะเป็นคนพิเศษคุณไม่ได้คำนึงถึงแฟร์มาต์!
wchargin

"ระยะเวลาของเมโลดี้ต้องอยู่ระหว่าง 30 และ 70 วินาที" นี่เป็นเวลาสั้น ๆ ที่ 24 วินาที
งานอดิเรกของ Calvin

4
@ งานอดิเรกของ Calvin รอ ... ฉันทำทั้งหมดนี้ตามคำแนะนำ 50 BPM ... ฉันโทษคุณ: |
LegionMammal978

1
%1, %2และ%%ไม่จริงบันทึกใด ๆ ไบต์กว่าx="E5"-> x(ในความเป็นจริงที่เราได้เห็นว่าคุณมักจะใช้พวกเขาคุณควรบันทึกจริงค่อนข้างมากโดยใช้ตัวแปร) จากนั้นคุณสามารถบันทึกตันไบต์โดยใช้และจัดเก็บโน้ตที่ใช้มากที่สุดในEmitSount@Sound[SoundNote[#,5/#2,"Trumpet",SoundVolume->#3/17]&@@@{{%%,8,17},{%%,24,20},...} %และเมื่อวันที่ 24 บันทึกย่ออาจจะยังสั้นกว่าเพื่อแบ่งรายการแบบแบน:SoundNote[#,5/#2,"Trumpet",SoundVolume->#3/17&@@@{%%,8,17,%%,24,20,%2,2,23,...}~Partition~3
Martin Ender

5

Sonic Pi, 899 ไบต์

เวลาค่อนข้างน้อย แต่ฉันคิดว่ามันโอเค

golfed เบา ๆ :

use_synth: ใบมีด
use_synth_defaults ยั่งยืน: 0.70, ปล่อย: 0.0
เล่น: G4 ปล่อย: 0.05
รอ 0.75
เล่น: G4 รักษา: 0.25
รอ 0.25
ถือ = rrand_i (3,4)
เล่น: C5 รักษา: ถือปล่อย: 0.5
รอกด + 0.5
เล่น: G4 ปล่อย: 0.05
รอ 0.75
เล่น: C5 รักษา: 0.25
นอนหลับ 0.25
ถือ = rrand_i (3,4)
เล่น: E5 รักษา: ถือปล่อย: 1.25
นอนค้าง + 1.25
เล่น: G4
นอนหลับ 0.70
เล่น: C5
นอนหลับ 0.70
2. เวลาทำ
  เล่น: E5 รักษา: 1, ข่าว: 0.25
  นอนหลับ 1.25
  เล่น: G4
  นอน 0.7
  เล่น: C5
  นอน 0.7
ปลาย
ถือ = rrand_i (3,5)
เล่น: E5 รักษา: ถือปล่อย: 0.75
sleep sleep + 1
เล่น: C5 ปล่อย: 0.05
นอนหลับ 0.75
เล่น: E5 รักษา: 0.25
นอนหลับ 0.25
เล่น: G5 รักษา: 2.45 ปล่อย: 0.05
นอนหลับ 2.5
เล่น: E5 รักษา: 1, ข่าว: 0.25
นอนหลับ 1.25
เล่น: C5 รักษา: 1, ข่าว: 0.25
นอนหลับ 1.25
ถือ = rrand_i (3,5)
เล่น: G4 รักษา: ถือปล่อย: 0.5
กดค้างไว้ + 0.5
เล่น: G4 ปล่อย: 0.05
นอนหลับ 0.75
เล่น: G4 รักษา: 0.25
นอนหลับ 0.25
ถือ = rrand_i (3,5)
เล่น: C5 รักษา: ถือปล่อย: 1.5

ใช่มีคนใช้ Sonic Pi!
Mega Man

สามารถเล่นกอล์ฟได้เล็กน้อยผ่านการเปลี่ยนชื่อโฮลด์ด้วย h เปลี่ยนการปล่อย: 0.0 ถึงรีลีส: 0 และการลบช่องว่าง
Mega Man

4

MATLAB, 338 327 262 258 230 ไบต์

o=@(L,f)sin(pi*.11*2^(f/12))*(1:600*L))
sound([o(3,-1) o(1,-1) o(12,2) o(3,-1) o(1,2) o(12,4) o(2,-1) o(2,2) o(4,4) o(2,-1) o(2,2) o(4,4) o(2,-1) o(2,2) o(12,4) o(3,2) o(1,4) o(8,6) o(4,4) o(4,2) o(12,-1) o(3,-1) o(1,-1) o(12,4)])

2

SmileBASIC ขนาด 73 ไบต์

BGMPLAY"@56T50L2.G8.G16B+G8.<C16E>[G8<C8E4>]2G8<C8EC8.E16G2E4C4>GG8.G16B+

บันทึกและการกำหนดเวลาทั้งหมดถูกต้อง ฉันใช้ทรัมเป็ตเพราะมันเป็นสิ่งที่ใกล้เคียงที่สุดใน MIDI

<audio autoplay controls src="//12me21.github.io/resources/taps.mp3"></audio>


1

Powershell, 183 175 159 bytes

ทริปคิดถึงใครไม่ชอบบี๊บ?!

foreach($i in 0..23){[console]::beep((196,262,330,392)[(001012012012012123210001-split'')[$i]],(3,1,12,3,1,12,2,2,4,2,2,4,2,2,12,3,1,8,4,4,12,3,1,12)[$i]*400)}


คำอธิบาย (sortof)

foreach($i in 0..23) { # foreach loop which ranges from 0 to 23
    [console]::beep( # [console]::beep(Pitch, Duration)
        (196,262,330,392) # the notes in Hertz
            [ # select which note to use
                (001012012012012123210001-split'') # -split '' creates an array of [0,0,1,0,1 ...], spaces can be omitted
                [$i] # select the n-th element
            ],
        (3,1,12,3,1,12,2,2,4,2,2,4,2,2,12,3,1,8,4,4,12,3,1,12) # array of durations
        [$i]*400 # duration in milliseconds * 400
    )
}


สิ่งนี้จะเล่นในประมาณ 45 วินาที

นี่เป็นครั้งแรกที่ฉันใช้ Powershell ของ Windows เคล็ดลับใด ๆ ในการตีกอล์ฟนี่เป็นเรื่องที่น่ายินดี


รุ่นเก่า

175

foreach($i in(0..23)){[console]::beep((196,262,330,392)[(0,0,1,0,1,2,0,1,2,0,1,2,0,1,2,1,2,3,2,1,0,0,0,1)[$i]],(3,1,12,3,1,12,2,2,4,2,2,4,2,2,12,3,1,8,4,4,12,3,1,12)[$i]*400)}

183

$d=3,1,12,3,1,12,2,2,4,2,2,4,2,2,12,3,1,8,4,4,12,3,1,12;$n=0,0,1,0,1,2,0,1,2,0,1,2,0,1,2,1,2,3,2,1,0,0,0,1;foreach($i in(0..23)){[console]::beep((196,262,330,392)[$n[$i]],$d[$i]*400)}

1

BBC Basic, 111

ดาวน์โหลดล่ามได้ที่http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

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

FORk=1TO24
  x=ASC(MID$("')F'Lb(Ke(Ke(KbJhxeI#')F",k))
  SOUND1,-9,x DIV7*4+60,INT(12/1.4^(x MOD7))*5
  SOUND1,0,1,1
NEXT

การบีบอัดมาตรฐานอย่างเป็นธรรม 1 ตัวอักษร ASCII ต่อโน้ต พารามิเตอร์ของSOUNDมีดังนี้:

Channel (always 1 for the purposes of this challenge)
Amplitude (negative for on, 0 for off, positive is an envelope index)
Pitch (in increments of 1/4 semitone, with middle C at 100)
Duration (20ths of a second)

ช่วงของเพลงคือ 13 โน้ตแม้ว่าจะใช้เพียง 4 เพื่อให้ช่วงนี้อยู่ในช่วง 95 จำนวนของ ASCII ที่พิมพ์ได้ฉันต้องบีบระยะเวลาเป็นช่วงจำนวนเต็ม 7 และเอาโมดูโล 7 มาใช้ช่วงเวลาต่อไปนี้ (ในสิบหก) ไม่รวม 6 ข้อ ใช้แล้ว): 1,2,3,4,6,8,12 ในการสร้างตัวเลขเหล่านี้ฉันกดความคิดของการหาร 12 ด้วยพลังของsqrt(2)(ประมาณ 1.4) และตัดทอน

SOUND1,0,1,1เป็นแกล้งต้นทุน 12 ไบต์ จำเป็นต้องมีการหยุดชั่วคราวระหว่างบันทึกย่อของระดับเสียงที่เหมือนกัน


1

Ruby + เสียงบี๊บ, 178 ไบต์

f=[260,346,416,499]
n=[12,*1..4]
l=(a="001012012012012123210001310310224224220318440310".chars.map(&:to_i))[24..-1]
`beep#{24.times.map{|i|" -f#{f[a[i]]} -l#{n[l[i]]}00"}*" -n"}`

พาฉันไปชั่วขณะหนึ่งเพื่อทำสิ่งนี้ฉันคิดว่าฉันพลาดเรือ แต่ไม่ว่าอะไรก็ตาม

fเก็บสี่ความถี่ที่ใช้ nเก็บความยาวโน้ตได้ห้าระดับที่ใช้ในบันทึกทวีคูณของ 16

a="00101...เก็บรักษาระดับเสียงโน้ตทั้งหมดตามด้วยความยาวโน้ตทั้งหมดตามดัชนีในอาร์เรย์ที่เกี่ยวข้อง lมีการตั้งค่าจากนั้นไปที่ Indice 24 aและเป็นต้นไปของ จากนั้นคำสั่งเสียงบี๊บจะถูกสร้างขึ้นโดยวนซ้ำตามข้างต้นทั้งหมดและดำเนินการ


0

C - (ดิบ: 318 | WAV: 437)

PCM โมโน 8 บิต (ไม่มีลายเซ็น) ที่ 44800 Hz, 33.60 วินาที

การเปลี่ยนแปลง mezzo forte, fortissimo และ forte นั้นถูกนำมาใช้อย่างมีศิลปะ แฟร์มาต์น่าจะดีกว่า

รหัสขึ้นอยู่กับunsigned long long8 octets และระบบ endian น้อย

#include<stdio.h>
#include<math.h>
#ifdef RAW
main(){unsigned long long D[]={0x422422c13c13,0xc13c44813c22},X[]={27863,37193,46860,55727},O=0x406e64924910,i=0,j;float Z,A,U=40,P;for(;i<24;D[i++/12]>>=4){Z=X[O&3]/1e6;P=0;O>>=2;A=i>18?--U:i<14?U+i/2:U+30;for(j=(D[i/12]&15)*13440;j;A-=--j<7e3&&A>0?.01:0)putchar(A*sin(P+=Z)+128);}}
#else
main(){unsigned long long D[]={0x422422c13c13,0xc13c44813c22},X[]={27863,37193,46860,55727},O=0x406e64924910,i=0,j;float Z,A,U=40,P;int W[]={0x46464952,1570852,0x45564157,544501094,16,65537,44800,44800,524289,0x61746164,1505280};fwrite(W,4,11,stdout);for(;i<24;D[i++/12]>>=4){Z=X[O&3]/1e6;P=0;O>>=2;A=i>18?--U:i<14?U+i/2:U+30;for(j=(D[i/12]&15)*13440;j;A-=--j<7e3&&A>0?.01:0)putchar(A*sin(P+=Z)+128);}}
#endif

รวบรวมและเรียกใช้กับสิ่งที่ชอบ:

gcc -std=c99 -o taps taps.c -lm
./taps > taps.wav
play taps.wav

เพิ่ม-DRAWในบรรทัดรวบรวมสำหรับชุดตัวเลือกดิบ

เอ้าท์พุทดิบสามารถเล่นกับ SoX ได้playเช่น:

play -c 1 -b 8 -r 44800 -t u8 <file>
       |    |       |       |
       |    |       |       +--- Unsigned 8-bit
       |    |       +----------- Sample rate
       |    +------------------- 8 Bits
       +------------------------ 1 Channel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.