diff --git a/2017/15/15.md b/2017/15/15.md
new file mode 100644
index 0000000..9a1455d
--- /dev/null
+++ b/2017/15/15.md
@@ -0,0 +1,138 @@
+## \-\-- Day 15: Dueling Generators \-\--
+
+Here, you encounter a pair of dueling
+generators.
+The generators, called *generator A* and *generator B*, are trying to
+agree on a sequence of numbers. However, one of them is malfunctioning,
+and so the sequences don\'t always match.
+
+As they do this, a *judge* waits for each of them to generate its next
+value, compares the lowest 16 bits of both values, and keeps track of
+the number of times those parts of the values match.
+
+The generators both work on the same principle. To create its next
+value, a generator will take the previous value it produced, multiply it
+by a *factor* (generator A uses `16807`; generator B uses `48271`), and
+then keep the remainder of dividing that resulting product by
+`2147483647`. That final remainder is the value it produces next.
+
+To calculate each generator\'s first value, it instead uses a specific
+starting value as its \"previous value\" (as listed in your puzzle
+input).
+
+For example, suppose that for starting values, generator A uses `65`,
+while generator B uses `8921`. Then, the first five pairs of generated
+values are:
+
+ --Gen. A-- --Gen. B--
+ 1092455 430625591
+ 1181022009 1233683848
+ 245556042 1431495498
+ 1744312007 137874439
+ 1352636452 285222916
+
+In binary, these pairs are (with generator A\'s value first in each
+pair):
+
+ 00000000000100001010101101100111
+ 00011001101010101101001100110111
+
+ 01000110011001001111011100111001
+ 01001001100010001000010110001000
+
+ 00001110101000101110001101001010
+ 01010101010100101110001101001010
+
+ 01100111111110000001011011000111
+ 00001000001101111100110000000111
+
+ 01010000100111111001100000100100
+ 00010001000000000010100000000100
+
+Here, you can see that the lowest (here, rightmost) 16 bits of the third
+value match: `1110001101001010`. Because of this one match, after
+processing these five pairs, the judge would have added only `1` to its
+total.
+
+To get a significant sample, the judge would like to consider *40
+million* pairs. (In the example above, the judge would eventually find a
+total of `588` pairs that match in their lowest 16 bits.)
+
+After 40 million pairs, *what is the judge\'s final count*?
+
+Your puzzle answer was `573`.
+
+The first half of this puzzle is complete! It provides one gold star: \*
+
+## \-\-- Part Two \-\-- {#part2}
+
+In the interest of trying to align a little better, the generators get
+more picky about the numbers they actually give to the judge.
+
+They still generate values in the same way, but now they only hand a
+value to the judge when it meets their *criteria*:
+
+- Generator A looks for values that are multiples of `4`.
+- Generator B looks for values that are multiples of `8`.
+
+Each generator functions completely *independently*: they both go
+through values entirely on their own, only occasionally handing an
+acceptable value to the judge, and otherwise working through the same
+sequence of values as before until they find one.
+
+The judge still waits for each generator to provide it with a value
+before comparing them (using the same comparison method as before). It
+keeps track of the order it receives values; the first values from each
+generator are compared, then the second values from each generator, then
+the third values, and so on.
+
+Using the example starting values given above, the generators now
+produce the following first five values each:
+
+ --Gen. A-- --Gen. B--
+ 1352636452 1233683848
+ 1992081072 862516352
+ 530830436 1159784568
+ 1980017072 1616057672
+ 740335192 412269392
+
+These values have the following corresponding binary values:
+
+ 01010000100111111001100000100100
+ 01001001100010001000010110001000
+
+ 01110110101111001011111010110000
+ 00110011011010001111010010000000
+
+ 00011111101000111101010001100100
+ 01000101001000001110100001111000
+
+ 01110110000001001010100110110000
+ 01100000010100110001010101001000
+
+ 00101100001000001001111001011000
+ 00011000100100101011101101010000
+
+Unfortunately, even though this change makes more bits similar on
+average, none of these values\' lowest 16 bits match. Now, it\'s not
+until the 1056th pair that the judge finds the first match:
+
+ --Gen. A-- --Gen. B--
+ 1023762912 896885216
+
+ 00111101000001010110000111100000
+ 00110101011101010110000111100000
+
+This change makes the generators much slower, and the judge is getting
+impatient; it is now only willing to consider *5 million* pairs. (Using
+the values from the example above, after five million pairs, the judge
+would eventually find a total of `309` pairs that match in their lowest
+16 bits.)
+
+After 5 million pairs, but using this new generator logic, *what is the
+judge\'s final count*?
+
+Answer:
+
+Although it hasn\'t changed, you can still [get your puzzle
+input](15/input).
diff --git a/2017/15/debug-full-aoc-response.html b/2017/15/debug-full-aoc-response.html
new file mode 100644
index 0000000..405594c
--- /dev/null
+++ b/2017/15/debug-full-aoc-response.html
@@ -0,0 +1,112 @@
+
+
+
You don't seem to be solving the right level. Did you already complete it? [Return to Day 15]
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2017/15/solution.py b/2017/15/solution.py
new file mode 100644
index 0000000..75f02dd
--- /dev/null
+++ b/2017/15/solution.py
@@ -0,0 +1,72 @@
+#!/bin/python3
+import sys,re
+from pprint import pprint
+sys.path.insert(0, '../../')
+from fred import list2int
+
+input_f = 'test'
+
+part = 2
+#########################################
+# #
+# Part 1 #
+# #
+#########################################
+
+if part == 1:
+ a = 634
+ b = 301
+ a_fak = 16807
+ b_fak = 48271
+ rem = 2147483647
+ count = 0
+ for i in range(0,40000000):
+ a = (a*a_fak)%rem
+ b = (b*b_fak)%rem
+
+ a_bin = bin(a)[2:].zfill(32)
+ b_bin = bin(b)[2:].zfill(32)
+ if a_bin[16:] == b_bin[16:]:
+ count += 1
+
+ print(count)
+
+
+
+
+
+
+#########################################
+# #
+# Part 2 #
+# #
+#########################################
+if part == 2:
+ a = 634
+ b = 301
+ a_fak = 16807
+ b_fak = 48271
+ rem = 2147483647
+ count = 0
+
+ a_matches = []
+ b_matches = []
+
+ while min(len(a_matches),len(b_matches)) < 5000000:
+ a = (a*a_fak)%rem
+ b = (b*b_fak)%rem
+
+ a_bin = bin(a)[2:].zfill(32)
+ b_bin = bin(b)[2:].zfill(32)
+ if a % 4 == 0:
+ a_matches.append(a_bin[16:])
+ if b % 8 == 0:
+ b_matches.append(b_bin[16:])
+
+ print(len(a_matches))
+ print(len(b_matches))
+ for x in range(0,min(len(a_matches),len(b_matches))):
+ if a_matches[x] == b_matches[x]:
+ count += 1
+
+ print(count)
diff --git a/2017/16/16.md b/2017/16/16.md
new file mode 100644
index 0000000..8306abd
--- /dev/null
+++ b/2017/16/16.md
@@ -0,0 +1,59 @@
+## \-\-- Day 16: Permutation Promenade \-\--
+
+You come upon a very unusual sight; a group of programs here appear to
+be [dancing](https://www.youtube.com/watch?v=lyZQPjUT5B4&t=53).
+
+There are sixteen programs in total, named `a` through `p`. They start
+by standing in a line: `a` stands
+in position `0`, `b` stands in position `1`, and so on until `p`, which
+stands in position `15`.
+
+The programs\' *dance* consists of a sequence of *dance moves*:
+
+- *Spin*, written `sX`, makes `X` programs move from the end to the
+ front, but maintain their order otherwise. (For example, `s3` on
+ `abcde` produces `cdeab`).
+- *Exchange*, written `xA/B`, makes the programs at positions `A` and
+ `B` swap places.
+- *Partner*, written `pA/B`, makes the programs named `A` and `B` swap
+ places.
+
+For example, with only five programs standing in a line (`abcde`), they
+could do the following dance:
+
+- `s1`, a spin of size `1`: `eabcd`.
+- `x3/4`, swapping the last two programs: `eabdc`.
+- `pe/b`, swapping programs `e` and `b`: `baedc`.
+
+After finishing their dance, the programs end up in order `baedc`.
+
+You watch the dance for a while and record their dance moves (your
+puzzle input). *In what order are the programs standing* after their
+dance?
+
+Your puzzle answer was `ehdpincaogkblmfj`.
+
+The first half of this puzzle is complete! It provides one gold star: \*
+
+## \-\-- Part Two \-\-- {#part2}
+
+Now that you\'re starting to get a feel for the dance moves, you turn
+your attention to *the dance as a whole*.
+
+Keeping the positions they ended up in from their previous dance, the
+programs perform it again and again: including the first dance, a total
+of *one billion* (`1000000000`) times.
+
+In the example above, their second dance would *begin* with the order
+`baedc`, and use the same dance moves:
+
+- `s1`, a spin of size `1`: `cbaed`.
+- `x3/4`, swapping the last two programs: `cbade`.
+- `pe/b`, swapping programs `e` and `b`: `ceadb`.
+
+*In what order are the programs standing* after their billion dances?
+
+Answer:
+
+Although it hasn\'t changed, you can still [get your puzzle
+input](16/input).
diff --git a/2017/16/solution.py b/2017/16/solution.py
new file mode 100644
index 0000000..53a7800
--- /dev/null
+++ b/2017/16/solution.py
@@ -0,0 +1,132 @@
+#!/bin/python3
+import sys,re,collections
+
+from pprint import pprint
+sys.path.insert(0, '../../')
+from fred import list2int
+
+input_f = 'input'
+
+part = 2
+#########################################
+# #
+# Part 1 #
+# #
+#########################################
+
+inst = []
+
+programs = 'abcdefghijklmnop'
+#programs = 'abcde'
+
+def parse_input(input_str):
+ pattern = r"^(s(\d+)|x(\d+)/(\d+)|p([a-zA-Z])/([a-zA-Z]))$"
+
+ match = re.match(pattern, input_str)
+ if match:
+ if match.group(2):
+ return ('s', int(match.group(2)))
+ elif match.group(3) and match.group(4):
+ return ('x', int(match.group(3)), int(match.group(4)))
+ elif match.group(5) and match.group(6):
+ return ('p', match.group(5), match.group(6))
+ return None
+
+def swap_pos(d, index1, index2):
+ if not (0 <= index1 < len(d)) or not (0 <= index2 < len(d)):
+ raise IndexError("Index out of range")
+ d[index1], d[index2] = d[index2], d[index1]
+
+def swap_items(d, item1, item2):
+ try:
+ index1 = d.index(item1)
+ index2 = d.index(item2)
+
+ d[index1], d[index2] = d[index2], d[index1]
+ except ValueError as e:
+ raise ValueError(f"One or both items not found in deque: {e}")
+
+if part == 1:
+ with open(input_f) as file:
+ for line in file:
+ instructions = line.rstrip().split(',')
+
+ programs = collections.deque(list(programs))
+
+ #print(programs)
+ #print(instructions)
+ print(len(instructions))
+
+ for idx,i in enumerate(instructions):
+ inst = parse_input(i)
+ print(idx,end=' ')
+ #print(i)
+ #rint(inst)
+ if inst[0] == 's':
+ #print('Spin', i)
+ programs.rotate(inst[1])
+
+ elif inst[0] == 'x':
+ #print('Exchange',i)
+ swap_pos(programs,inst[1],inst[2])
+
+ elif inst[0] == 'p':
+ #print('Partner',i)
+ swap_items(programs,inst[1],inst[2])
+ else:
+ print(inst)
+ input()
+
+
+
+ for i in programs:
+ print(i,end='')
+ print()
+
+
+#########################################
+# #
+# Part 2 #
+# #
+#########################################
+if part == 2:
+
+
+ with open(input_f) as file:
+ for line in file:
+ instructions = line.rstrip().split(',')
+
+ programs = collections.deque(list(programs))
+
+ #print(programs)
+ #print(instructions)
+ print(len(instructions))
+
+ for r in range(0,1000000000):
+ for idx,i in enumerate(instructions):
+ inst = parse_input(i)
+ #print(idx,end=' ')
+ #print(i)
+ #rint(inst)
+ if inst[0] == 's':
+ #print('Spin', i)
+ programs.rotate(inst[1])
+
+ elif inst[0] == 'x':
+ #print('Exchange',i)
+ swap_pos(programs,inst[1],inst[2])
+
+ elif inst[0] == 'p':
+ #print('Partner',i)
+ swap_items(programs,inst[1],inst[2])
+ else:
+ print(inst)
+ input()
+ if r % 10000 == 0:
+ print(r)
+
+
+
+ for i in programs:
+ print(i,end='')
+ print()
\ No newline at end of file