Day 9 Complete

This commit is contained in:
Brian Buller 2016-12-09 09:59:13 -06:00
parent 39d8900ccf
commit dafcc91468
5 changed files with 216 additions and 0 deletions

BIN
day09/day09 Executable file

Binary file not shown.

1
day09/input Normal file

File diff suppressed because one or more lines are too long

125
day09/main.go Normal file
View File

@ -0,0 +1,125 @@
package main
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"regexp"
"strconv"
)
var re *regexp.Regexp
func main() {
var input []byte
var noDecompress bool
var printSize bool
if len(os.Args) > 1 {
for i := 1; i < len(os.Args); i++ {
if os.Args[i][0] != '-' {
// Assume it's a filename
// Read from the given filename
input = fileToByteSlice(os.Args[1])
} else {
switch os.Args[i] {
case "-size":
printSize = true
case "-dry":
// -dry implies printSize
printSize = true
noDecompress = true
}
}
}
}
if len(input) == 0 {
// Must be stdin
input = stdinToByteSlice()
}
input = bytes.TrimSpace(input)
// re matches compression markers and submatches the values we care about
re = regexp.MustCompile(`\((\d*)x(\d*)\)`)
if noDecompress {
cnt := depthDecompressLength(input)
fmt.Println("Total Decompressed Bytes:", cnt)
os.Exit(0)
}
output := depthDecompress(input)
fmt.Println(string(output))
if printSize {
fmt.Println("Total Decompressed Bytes:", len(output))
}
}
// depthDecompressLength counts how many uncompressed bytes are
// in the byte slice by unravelling the compression levels
// recursively
func depthDecompressLength(cmp []byte) uint64 {
mrkParts := re.FindStringSubmatch(string(cmp))
if len(mrkParts) < 3 {
// No compressionmarker, just return cmp length
return uint64(len(cmp))
}
marker, mrkBytes, mrkDupe := []byte(mrkParts[0]), atoi(mrkParts[1]), atoi(mrkParts[2])
mrkPos := bytes.Index(cmp, marker)
if mrkPos > 0 {
cmp = cmp[mrkPos:]
}
recurBytes := bytes.TrimPrefix(cmp, marker)[:mrkBytes]
remainder := bytes.TrimPrefix(cmp, append(marker, recurBytes...))
return uint64(mrkPos) + (depthDecompressLength(recurBytes) * uint64(mrkDupe)) + depthDecompressLength(remainder)
}
func depthDecompress(cmp []byte) []byte {
mrkParts := re.FindStringSubmatch(string(cmp))
if len(mrkParts) < 3 {
// No compression marker, just return cmp length
return cmp
}
marker, mrkBytes, mrkDupe := []byte(mrkParts[0]), atoi(mrkParts[1]), atoi(mrkParts[2])
mrkPos := bytes.Index(cmp, marker)
var ret []byte
if mrkPos > 0 {
ret = cmp[:mrkPos]
cmp = cmp[mrkPos:]
}
recurBytes := bytes.TrimPrefix(cmp, marker)[:mrkBytes]
remainder := bytes.TrimPrefix(cmp, append(marker, recurBytes...))
ret = append(ret, bytes.Repeat(depthDecompress(recurBytes), mrkDupe)...)
return append(ret, depthDecompress(remainder)...)
//return bytes.Repeat(depthDecompress(recurBytes), mrkDupe) + depthDecompress(remainder)
}
func fileToByteSlice(fn string) []byte {
var c []byte
var err error
c, err = ioutil.ReadFile(fn)
if err != nil {
fmt.Println("Unable to read file: " + fn)
os.Exit(1)
}
return c
}
func stdinToByteSlice() []byte {
var input string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input += scanner.Text()
}
return []byte(input)
}
func atoi(i string) int {
var ret int
var err error
if ret, err = strconv.Atoi(i); err != nil {
log.Fatal("Invalid Atoi")
}
return ret
}

70
day09/problem Normal file
View File

@ -0,0 +1,70 @@
Advent of Code
--- Day 9: Explosives in Cyberspace ---
Wandering around a secure area, you come across a datalink port to a new part of the network. After briefly scanning it for
interesting files, you find one file in particular that catches your attention. It's compressed with an experimental format, but
fortunately, the documentation for the format is nearby.
The format compresses a sequence of characters. Whitespace is ignored. To indicate that some sequence should be repeated, a marker is
added to the file, like (10x2). To decompress this marker, take the subsequent 10 characters and repeat them 2 times. Then, continue
reading the file after the repeated data. The marker itself is not included in the decompressed output.
If parentheses or other characters appear within the data referenced by a marker, that's okay - treat it like normal data, not a
marker, and then resume looking for markers after the decompressed section.
For example:
 ADVENT contains no markers and decompresses to itself with no changes, resulting in a decompressed length of 6.
 A(1x5)BC repeats only the B a total of 5 times, becoming ABBBBBC for a decompressed length of 7.
• (3x3)XYZ becomes XYZXYZXYZ for a decompressed length of 9.
 A(2x2)BCD(2x2)EFG doubles the BC and EF, becoming ABCBCDEFEFG for a decompressed length of 11.
• (6x1)(1x3)A simply becomes (1x3)A - the (1x3) looks like a marker, but because it's within a data section of another marker, it
is not treated any differently from the A that comes after it. It has a decompressed length of 6.
 X(8x2)(3x3)ABCY becomes X(3x3)ABC(3x3)ABCY (for a decompressed length of 18), because the decompressed data from the (8x2) marker
(the (3x3)ABC) is skipped and not processed further.
What is the decompressed length of the file (your puzzle input)? Don't count whitespace.
Your puzzle answer was __________.
--- Part Two ---
Apparently, the file actually uses version two of the format.
In version two, the only difference is that markers within decompressed data are decompressed. This, the documentation explains,
provides much more substantial compression capabilities, allowing many-gigabyte files to be stored in only a few kilobytes.
For example:
• (3x3)XYZ still becomes XYZXYZXYZ, as the decompressed section contains no markers.
 X(8x2)(3x3)ABCY becomes XABCABCABCABCABCABCY, because the decompressed data from the (8x2) marker is then further decompressed,
thus triggering the (3x3) marker twice for a total of six ABC sequences.
• (27x12)(20x12)(13x14)(7x10)(1x12)A decompresses into a string of A repeated 241920 times.
• (25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN becomes 445 characters long.
Unfortunately, the computer you brought probably doesn't have enough memory to actually decompress the file; you'll have to come up
with another way to get its decompressed length.
What is the decompressed length of the file using this improved format?
Although it hasn't changed, you can still get your puzzle input.
Answer: _____________________ [ [Submit] ]
References
Visible links
. http://adventofcode.com/
. http://adventofcode.com/2016/about
. http://adventofcode.com/2016/support
. http://adventofcode.com/2016/events
. http://adventofcode.com/2016/settings
. http://adventofcode.com/2016/auth/logout
. http://adventofcode.com/2016
. http://adventofcode.com/2016
. http://adventofcode.com/2016/leaderboard
. http://adventofcode.com/2016/stats
. http://adventofcode.com/2016/sponsors
. http://adventofcode.com/2016/sponsors
. http://adventofcode.com/2016/day/9/input

View File

@ -2,6 +2,7 @@ package aoc
import (
"bufio"
"fmt"
"log"
"os"
"strconv"
@ -28,3 +29,22 @@ func atoi(i string) int {
}
return ret
}
func stdinToString() string {
var input string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input += scanner.Text()
}
return input
}
func fileToString(fn string) string {
var c []byte
c, err = ioutil.Readfile(filename)
if err != nil {
fmt.Println("Unable to read file: " + filename)
os.Exit(1)
}
return string(c)
}