Created
April 4, 2020 23:27
-
-
Save flubstep/2f76e1cf1e53f83d8439df8d46fdf967 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import logging | |
logging.basicConfig(filename='esab.log', filemode='w', level=logging.INFO, format='%(message)s') | |
def invert(b): | |
return 1 - b | |
def read_bit(b): | |
print(b + 1) | |
line = input() | |
logging.info(f'bits[{b}] = {line}') | |
return int(line) | |
class Chunk(object): | |
def __init__(self, start_index, end_index, forward_bits, reverse_bits): | |
self.start_index = start_index | |
self.end_index = end_index | |
self.forward_bits = forward_bits | |
self.reverse_bits = reverse_bits | |
# Pre-calculate match_index and diff_index | |
self.calculate_alignment_indices() | |
def calculate_alignment_indices(self): | |
self.match_index = None | |
self.match_value = None | |
self.diff_index = None | |
self.diff_value = None | |
# Get one match_index and one diff_index | |
zip_bits = zip(self.forward_bits, self.reverse_bits) | |
for index, (bit, bit_) in enumerate(zip_bits): | |
if bit == bit_ and self.match_index is None: | |
self.match_index = self.start_index + index | |
self.match_value = bit | |
if bit != bit_ and self.diff_index is None: | |
self.diff_index = self.start_index + index | |
self.diff_value = bit | |
def get_current_value_from_reads(self, match_index_value, diff_index_value): | |
is_inverted = self.match_index != None and (match_index_value != self.match_value) | |
is_reversed = ( | |
(is_inverted and diff_index_value == self.diff_value) or | |
(not is_inverted and diff_index_value != self.diff_value) | |
) | |
ret = self.copy() | |
if is_inverted: | |
ret = ret.invert() | |
if is_reversed: | |
ret = ret.reverse() | |
logging.info(f'Inv: {is_inverted} Rev: {is_reversed} Aligning: {str(self)} -> {str(ret)}') | |
return ret | |
def __str__(self): | |
return ( | |
''.join(str(b) for b in self.forward_bits) + | |
''.join(str(b) for b in reversed(self.reverse_bits)) | |
) | |
def copy(self): | |
return Chunk( | |
start_index=self.start_index, | |
end_index=self.end_index, | |
forward_bits=self.forward_bits[:], | |
reverse_bits=self.reverse_bits[:], | |
) | |
def invert(self): | |
return Chunk( | |
start_index=self.start_index, | |
end_index=self.end_index, | |
forward_bits=[invert(b) for b in self.forward_bits], | |
reverse_bits=[invert(b) for b in self.reverse_bits], | |
) | |
def reverse(self): | |
return Chunk( | |
start_index=self.start_index, | |
end_index=self.end_index, | |
forward_bits=self.reverse_bits[:], | |
reverse_bits=self.forward_bits[:], | |
) | |
def read_chunk(start_index, end_index, num_bits): | |
logging.info(f'Reading chunk {start_index}:{end_index}') | |
forward_bits = [] | |
reverse_bits = [] | |
for index in range(start_index, end_index): | |
forward_bits.append(read_bit(index)) | |
reverse_bits.append(read_bit(num_bits - index - 1)) | |
return Chunk( | |
start_index=start_index, | |
end_index=end_index, | |
forward_bits=forward_bits, | |
reverse_bits=reverse_bits, | |
) | |
def align_chunk(chunk): | |
logging.info(f'Aligning chunk {chunk.start_index}:{chunk.end_index}') | |
match_index_value = None | |
diff_index_value = None | |
match_index_value = read_bit(chunk.match_index or 0) | |
diff_index_value = read_bit(chunk.diff_index or 0) | |
return chunk.get_current_value_from_reads(match_index_value, diff_index_value) | |
def concat_chunks(chunk1, chunk2): | |
# Invariant: chunk1 and chunk2 are present-aligned | |
logging.info(f'Concating chunks {chunk1.start_index}:{chunk2.end_index}') | |
if chunk1.end_index != chunk2.start_index: | |
raise Exception("cannot concat two non-adjacent chunks") | |
return Chunk( | |
start_index=chunk1.start_index, | |
end_index=chunk2.end_index, | |
forward_bits=chunk1.forward_bits + chunk2.forward_bits, | |
reverse_bits=chunk1.reverse_bits + chunk2.reverse_bits, | |
) | |
def submit_chunk(chunk): | |
logging.info("Final answer: " + str(chunk)) | |
print(str(chunk)) | |
correct = input().strip() | |
if correct == 'Y': | |
logging.info("Correct!") | |
return True | |
else: | |
logging.info("Nay.") | |
return False | |
def align_and_concat_chunks(chunks): | |
chunks = [align_chunk(c) for c in chunks] | |
merged = chunks[0] | |
for c in chunks[1:]: | |
merged = concat_chunks(merged, c) | |
return merged | |
def play10(): | |
chunk = read_chunk(0, 5, 10) # 10 reads | |
final = align_chunk(chunk) | |
return submit_chunk(final) | |
def play20(): | |
chunk1 = read_chunk(0, 5, 20) # 10 reads | |
chunk2 = read_chunk(5, 10, 20) # 10 reads | |
final = align_and_concat_chunks([chunk1, chunk2]) | |
return submit_chunk(final) | |
def play100(): | |
chunks = [] | |
# 100 reads | |
for i in range(10): | |
start_index = i * 5 | |
chunks.append(read_chunk(start_index, start_index + 5, 100)) | |
half1 = align_and_concat_chunks(chunks[0:5]) # 10 reads | |
half2 = align_and_concat_chunks(chunks[5:10]) # 10 reads | |
final = align_and_concat_chunks([half1, half2]) | |
return submit_chunk(final) | |
if __name__ == '__main__': | |
sol = int(sys.argv[1]) | |
T, B = sys.stdin.readline().split() | |
T = int(T) | |
B = int(B) | |
for _ in range(T): | |
if sol == 0: | |
if not play10(): | |
break | |
elif sol == 1: | |
if not play20(): | |
break | |
elif sol == 2: | |
if not play100(): | |
break | |
else: | |
raise Exception("Not a valid input number") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment