brainfuck - 617 616 604 bytes
+>>>>,[>++++[<-------->-]<[>>>>],]<<<<[>+<<+<+>>-]<[>+<-]+<+<<[>+>-<<-]>[<+>-]>[,+++++[>+++++<-]>>[<->-]<[>>>>>[>>>>]+[<<<<]<-]>>[<+>-]<<<]>[>>[,<]<<+++++++++<]<<<[-[+>>-<]>[>>[<+<+>>-]<<<<[>+>-<<-]>[<+>-]>[<<[<<<<]>>>>[[<<<<+>>>>-]>>>>]<<<<+>>-]>[>+<-]]<<<[-[+>]+<<<<]>>>>-<<<<<]>>>>>+++++[>----<-]>->[<+>>+<-]<[<<<[<<<<]+[>>>>]<-]>>[<+>-]<[<<<<]>>>++++[<-------->-]>[-[,+++>]+>>>[<<<->>]>]<<<<<[>-]>[>>]>>+[<++++[<++++++++>-]<]>>[+++++++++++++>>>>]<<<<----<+++[<<+<<[<<+<<]+[>>>>]<<<<-]<<<<[-<<<<]>[.,>>]<<<<<[<<<<]<++++++++++<<.<+<<+<<+<<+<<+<[.,>>]<<<<<[<<]>++++++++++<+<<+<<+<..<+<[.,>>]<[<<]<...<<.
This took me the better part of two days. I think it was worth it. There's probably parts that can be golfed more by changing what cell something is stored in or whatever, but right now I'm just happy I got it working.
This program would have to be completely different if the question didn't specify that the input would be sorted. The way this works is by constructing a list of 10 pins around the ones that are input. That's kind of confusing but maybe this will explain it better:
If you input these pins: [2, 3, 6, 8, 9]
First, the program does this: [2, 3, 6, 8, 9] + [10]
Then this: [2, 3, 6] + [7] + [8, 9, 10]
Then this: [2, 3] + [4, 5] + [6, 7, 8, 9, 10]
Finally, this: [1] + [2, 3, 4, 5, 6, 7, 8, 9, 10]
To build this: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
While it's doing that, it remembers which of the pins the user put there and which ones it put there. This strategy would be very difficult to use if the input wasn't sorted.
Another thing that the sorting make easier is detection of the number 10. Since brainfuck deals with individual bytes, not "numbers" per se, it could have been a pain in the ass, but the sorted input made it much easier for me to deal with. The reason for that has to do with how I stored data in the program. I take the input one character at time and subtract 32 from the result. If the cell is non-zero after that, I move forward 4 cells. before repeating. This means that I get a non-space byte of input every 4 cells, and I effectively store pins as their number + 16. However, 10 takes two bytes to type, so I had to special case it. If the input wasn't sorted, I'd have to look through the pins, but since it is sorted it will always be the last pin if it appears. I check if the (last byte of input + 1) == (the second last byte of input) and if so, it must be 10. I get rid of the last byte and set the second last one to what my system understands as "10". The characters '1'
and '0'
don't fit in a single byte, but the number 26 sure does!
Coming up with tricks just to make something work at all is my favourite part of using this language. :)
If you're interested in how this program works in more detail, you can see the program with the comments I used while writing it to make sure I remembered what everything did. Even writing comments in brainfuck is hard, since there's no comment syntax. Instead, every character except those in <[+.,-]>
are no-ops. It's easy to introduce bugs by accidentally including .
or ,
in your comments! That's why the grammar is so wonky and semicolons are everywhere.
EDIT: As an example of how easy this is to screw up: I used "non-space" in one of the comments! When I stripped all the non-bf characters from the source, the program I used to do that kept in the -
. Luckily it didn't break anything, but now I've removed it to save a byte. :)
EDIT II: It's been a while since I touched this one, haha. In another brainfuck answer on this site, I noticed that I accidentally used a comma in the commented version. Since the input had already been exhausted, it set the current cell to 0 (this is implementation dependant, but in my experience it's the most common behaviour). I fixed the bug, but it got me thinking. The idiomatic way to set a cell to 0 is [-]
(roughly while (*p) { *p--; }
), which is two bytes longer. Any time all the input has been read, I can use ,
instead. This saved me 2 bytes in that answer, and 12 in this one!
one flag at the very left; will be important later
+>>>>
all nonspace bytes of input separated by 3 empty cells; pin number `n` stored with value `n` plus 16
,[>++++[<-------->-]<[>>>>],]<<<<
test if last pin is 10
[>+<<+<+>>-]<[>+<-]+<+<<[>+>-<<-]>[<+>-]>
[
if not: find 10 minus the number it is; put that many placeholder pins (cells with value 1) at the end
,+++++[>+++++<-]>>[<->-]<[>>>>>[>>>>]+[<<<<]<-]>>[<+>-]<<<
]>
[
if so: get rid of '0' byte; convert '1' byte to 26 (10 plus 16)
>>[,<]<<+++++++++<
]<<<
pointer now sitting on the cell with the second greatest pin that was inputted (ie not a placeholder)
;;;;;;;
[
check for flag placed at the very beginning of the program; if present: break
-[+>>-<]>
[
find ((pin to our right) minus 1) minus pin to our left
move all pins left of us 4*(that value) cells and insert placeholder pins
>>[<+<+>>-]<<<<[>+>-<<-]>[<+>-]>[<<[<<<<]>>>>[[<<<<+>>>>-]>>>>]<<<<+>>-]>[>+<-]
]
find first non placeholder pin to our left
there has to be one because we haven't hit the flag yet
<<<[-[+>]+<<<<]>>>>-<<<<<
]>>>>>+
we have now added placeholder pins at the end and in the middle; all that's left is the beginning
subtract 17 from lowest pin and put that many placeholders to the left
++++[>----<-]>->[<+>>+<-]<[<<<[<<<<]+[>>>>]<-]>>[<+>-]
subtract 32 from an empty cell 2 to the left of the lowest pin; will be useful later
<[<<<<]>>>++++[<-------->-]>
placeholder pins have the value 1; real pins have a value somewhere between 17 and 26
normalize it by stepping through and setting every pin with value != 1 to 3 (0's ascii code is 2 higher than period so this will make it easier to print later)
[-[,+++>]+>>>[<<<->>]>]<<<<<[>-]>[>>]>>
start writing 32s across the board; hitting every second cell
that's every pin and the cell 2 to the right of each pin
this is done in such a way that it will only halt if adding 32 to a cell sets it to 0; which is why we subtracted 0 from an empty cell earlier
it will catch us and prevent an infinite loop
+[<++++[<++++++++>-]<]
now write 13 to each pin; this adds up to 46 or 48; which are exactly the ascii values we want
>>[+++++++++++++>>>>]
we happen to have made a 14; turn it into a 10 for a newline
<<<<----
we're so close now; i can taste it
we have a list of 10 pins; each one with the ascii value that needs to be written
we have 32 everywhere because we'll need spaces
we even have a newline
the only problem now is that our list looks like this:
;;;;;;;;;;;;;;;;;;;;;;;;
;;1 2 3 4 5 6 7 8 9 10;;
;;;;;;;;;;;;;;;;;;;;;;;;
and we need to print in this order:
;;;;;;;;;;;;;;;;;;;;;;;;
;;7 8 9 10 4 5 6 2 3 1;;
;;;;;;;;;;;;;;;;;;;;;;;;
it's a pretty simple fix
once we print a pin we obviously don't need to remember it any more
so we simply print the last 4 pins on the list; destroying them on the way
then we print the last 3; which have become the ones we want
then two; then one
<+++[<<+<<[<<+<<]+[>>>>]<<<<-]<<<<[-<<<<]
print pins 7 8 9 10
>[.,>>]
print pins 4 5 6
<<<<<[<<<<]<++++++++++<<.<+<<+<<+<<+<<+<[.,>>]
print pins 3 2
<<<<<[<<]>++++++++++<+<<+<<+<..<+<[.,>>]
print the final pin!! :)
<[<<]<...<<.