Skip to content

Instantly share code, notes, and snippets.

@ToadKing
Created February 29, 2024 06:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ToadKing/5c92191e8e89c1501723da2f318c6e40 to your computer and use it in GitHub Desktop.
Save ToadKing/5c92191e8e89c1501723da2f318c6e40 to your computer and use it in GitHub Desktop.
// example input
const input = `
Disc 1
Composed by
John Doe (1, 2, 6~10)
Foo Bar (3)
Arranged by
Some Guy (1~10)
Disc 2
Composed by
John Doe (3, 5, 7)
Arranged by
Foo Bar (1)
Baz Qux (2~6)
`
const parsed = {}
let curDisc
let curRole
for (const rawline of input.split('\n')) {
const line = rawline.trim()
if (!line) {
continue
}
const newDisc = line.match(/Disc (\d+)$/i)
if (newDisc) {
curDisc = Number(newDisc[1])
curRole = undefined
continue
}
const newRole = line.match(/^(.*)(?: by|:| by:)$/i)
if (newRole) {
curRole = newRole[1]
continue
}
const artistsAndTracks = line.match(/^(.*) \(([\d,-~ ]+)\)$/)
if (artistsAndTracks) {
const [, rawartists, rawtracks] = artistsAndTracks
const artists = rawartists.split(',').map(a => a.trim())
const tracks = rawtracks.split(',').map(t => {
const range = t.trim().match(/^(\d+)[-~](\d+)$/)
if (range) {
const [, rawfirst, rawlast] = range
const first = Number(rawfirst)
const last = Number(rawlast)
if (!(last > first)) {
throw new RangeError('range not start~end')
}
const nums = []
for (let i = first; i <= last; i++) {
nums.push(i)
}
return nums
} else {
const num = Number(t)
if (!num) {
throw new RangeError(`bad track number: ${t}`)
}
return [Number(t)]
}
}).flat().map(t => `${curDisc}.${t}`)
if (!parsed[curRole]) {
parsed[curRole] = {}
}
for (const artist of artists) {
if (!parsed[curRole][artist]) {
parsed[curRole][artist] = new Set()
}
for (const track of tracks) {
parsed[curRole][artist].add(track)
}
}
continue
}
throw new RangeError(`could not parse line: ${line}`)
}
for (const [role, artistsAndTracks] of Object.entries(parsed)) {
console.log(`${role}:`)
for (const [artist, tracks] of Object.entries(artistsAndTracks)) {
console.log(`${artist} (${[...tracks].join(', ')})`)
}
console.log('')
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment