Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import re
- # Parses ostr into a list of boards
- def parse(instr, ostr):
- numlines = instr.count('\n')+1
- i = 0
- boards = []
- # Kinda hacky solution of counting each numlines lines as a board, due to flexible delimiting
- while i<len(ostr):
- currboard = ''
- for _ in range(numlines):
- if i>=len(ostr):
- print("Incorrect formatting -- can't parse boards; weird number of non-empty lines")
- exit(0)
- currboard += '\n' + ostr[i]
- i += 1
- boards.append(currboard.strip())
- return boards
- # Makes sure the board is of the correct format
- def check_format(instr, board):
- regex = instr.replace('v', '[v^]')
- return re.fullmatch(regex.strip(), board.strip())
- # Util function for check_combinations
- def board_to_bitarray(board):
- switches = re.sub(r'[\n\-]', '', board)
- switches = switches.replace('v', '0').replace('^', '1')
- return int(switches, 2)
- # Makes sure we have all of the boards
- def check_combinations(boards, numswitches):
- allnums = range(2**numswitches)
- counts = {num:0 for num in allnums}
- for board in boards:
- counts[board_to_bitarray(board)] += 1
- missings = [num for num in allnums if counts[num]==0]
- extras = {num:counts[num] for num in allnums if counts[num]>1}
- return missings, extras
- # Util for more useful error messages
- # [bitarray_to_board(i, instr) for i in range(2**instr.count('v'))] is actually a valid solution to this challenge
- def bitarray_to_board(bitarray, instr):
- swidxs = [match.start() for match in re.finditer('v', instr)]
- newboard = [char for char in instr] # because python strings are immutable
- while bitarray!=0: # flip switches by bitshifting
- currbit = bitarray & 1
- if currbit:
- newboard[swidxs[-1]] = '^'
- swidxs = swidxs[:-1]
- bitarray = bitarray >> 1
- return ''.join(newboard)
- if __name__=='__main__':
- # Get input and output
- with open('input') as fi:
- instr = fi.read()
- with open('output') as fo:
- ostr = fo.readlines()
- ostr = [line.strip() for line in ostr if not line=='\n']
- # Read boards from output; check for formatting
- boards = parse(instr, ostr)
- for idx, board in enumerate(boards):
- if not check_format(instr, board):
- print('Board incorrectly formatted:\n' + board
- + ' starting at line ' + str(idx*(instr.count('\n')+1)+1) + '\n')
- exit(0)
- # Check for correctness
- missings, extras = check_combinations(boards, instr.count('v'))
- if len(missings) > 0:
- for bitarray in missings:
- print('Missing board:\n' + bitarray_to_board(bitarray, instr) + '\n')
- if len(extras) > 0:
- for bitarray, count in extras.items():
- print('Extra boards:\n' + bitarray_to_board(bitarray, instr)
- + ' appeared ' + str(count) + ' times\n')
- if len(missings)==0 and len(extras)==0:
- print('All correct!')
- # Sample solution
- # with open('input') as fi:
- # instr = fi.read()
- # with open('output', 'w') as fo:
- # boards = [bitarray_to_board(i, instr) for i in range(2**instr.count('v'))]
- # boards_formatted = [board + '\n\n' for board in boards]
- # fo.writelines(boards_formatted)
- # for board in boards_formatted: print(board)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement