HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Google FooBar XOR Checksum Challenge

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
xorgooglefoobarchallengechecksum

Problem

Google FooBar came up a few days ago and I took it as a challenge to learn python quickly while having fun. However, I ran into one challenge today that has left me stumped, I've come up with a solution that finds the correct result, however it is not fast enough for some test cases. How can I improve upon it?

Queue To Do


You're almost ready to make your move to destroy the LAMBCHOP doomsday device, but the security checkpoints that guard the underlying systems of the LAMBCHOP are going to be a problem.
You were able to take one down without tripping any alarms, which is great!
Except that as Commander Lambda's assistant, you've learned that the checkpoints are about to come under automated review,
which means that your sabotage will be discovered and your cover blown - unless you can trick the automated review system.


To trick the system, you'll need to write a program to return the same security checksum that the guards would have after they would have checked all the workers through.
Fortunately, Commander Lambda's desire for efficiency won't allow for hours-long lines, so the checkpoint guards have found ways to quicken the pass-through rate.
Instead of checking each and every worker coming through, the guards instead go over everyone in line while noting their security IDs, then allow the line to fill back up.
Once they've done that they go over the line again, this time leaving off the last worker.
They continue doing this, leaving off one more worker from the line each time but recording the security IDs of those they do check, until they skip the entire line,
at which point they XOR the IDs of all the workers they noted into a checksum and then take off for lunch.
Fortunately, the workers' orderly nature causes them to always line up in numerical order without any gaps.


For example, if the first worker in line has ID 0 and the security checkpoint line holds three workers, the process would look like this:

```

Solution

Let's improve the readability of your second snippet.

You can start by writing your reduce only once:

def answer(start, length):
    checksum = 0
    i = 0
    while length > 0:
        checksum ^= reduce(operator.xor, xrange(start, start+length), 0)
        start += length + i
        length -= 1
        i += 1
    return checksum


And use a for loop instead of the while:

def answer(start, length):
    checksum = 0
    for i in xrange(length):
        checksum ^= reduce(operator.xor, xrange(start, start+length), 0)
        start += length + i
        length -= 1
    return checksum


You can also remove the need for some operations with a decreasing range:

def answer(start, length):
    checksum = 0
    for size in xrange(length, 0, -1):
        checksum ^= reduce(operator.xor, xrange(start, start + size), 0)
        start += length
    return checksum


And this is as readable as you can get.

You can go up to the one-liner:

def answer(start, length):
    return reduce(
        operator.xor,
        (reduce(operator.xor,
                xrange(start + i * length, start + i * length + size),
                0)
         for i, size in enumerate(xrange(length, 0, -1))),
        0)


But I would advice against it as it is not readable anymore.

A more interesting change could be to modify the starting ID rather than the length of the queue as we go:

def answer(start, length):
    checksum = 0
    for i, begin in enumerate(xrange(start, start + length * length, length)):
        checksum ^= reduce(operator.xor, xrange(begin, begin + length - i), 0)
    return checksum


And extract the core functionality into its own function:

def xor_in_range(a, b):
    return reduce(operator.xor, xrange(a, b), 0)

def answer(start, length):
    return reduce(
        operator.xor,
        (xor_in_range(begin, begin+length-i)
          for i, begin in enumerate(xrange(start, start + length * length, length))),
        0)


All there is left to do is optimize xor_in_range for speed.

Code Snippets

def answer(start, length):
    checksum = 0
    i = 0
    while length > 0:
        checksum ^= reduce(operator.xor, xrange(start, start+length), 0)
        start += length + i
        length -= 1
        i += 1
    return checksum
def answer(start, length):
    checksum = 0
    for i in xrange(length):
        checksum ^= reduce(operator.xor, xrange(start, start+length), 0)
        start += length + i
        length -= 1
    return checksum
def answer(start, length):
    checksum = 0
    for size in xrange(length, 0, -1):
        checksum ^= reduce(operator.xor, xrange(start, start + size), 0)
        start += length
    return checksum
def answer(start, length):
    return reduce(
        operator.xor,
        (reduce(operator.xor,
                xrange(start + i * length, start + i * length + size),
                0)
         for i, size in enumerate(xrange(length, 0, -1))),
        0)
def answer(start, length):
    checksum = 0
    for i, begin in enumerate(xrange(start, start + length * length, length)):
        checksum ^= reduce(operator.xor, xrange(begin, begin + length - i), 0)
    return checksum

Context

StackExchange Code Review Q#149440, answer score: 2

Revisions (0)

No revisions yet.