From cd108514a2eb4ed2e799a01b186c214799d0dfbb Mon Sep 17 00:00:00 2001 From: cmccandless Date: Thu, 12 Oct 2017 13:45:36 -0500 Subject: [PATCH] two-bucket: Fix incorrect test case to resolve #794 --- exercises/two-bucket/example.py | 103 +++++++++++------------- exercises/two-bucket/two_bucket_test.py | 2 +- 2 files changed, 50 insertions(+), 55 deletions(-) diff --git a/exercises/two-bucket/example.py b/exercises/two-bucket/example.py index 3bca958aca..f27380e113 100644 --- a/exercises/two-bucket/example.py +++ b/exercises/two-bucket/example.py @@ -1,59 +1,54 @@ ''' -The solution follows the following approach: - -->Pour from first bucket to second - 1.Fill the first bucket and empty it into the second bucket. - 2.If first bucket is empty fill it. - 3.If the second bucket is full empty it. - 4.Repeat steps 1,2,3 till either the first or second bucket contains the - desired amount. - -->Pour from first bucket to second - 1.Fill the second bucket and empty it into the first bucket. - 2.If second bucket is empty fill it. - 3.If the firts bucket is full empty it. - 4.Repeat steps 1,2,3 till either the first or second bucket contains the - desired amount. + This solution implements a breadth-first search of the graph + of possible valid states for the two buckets until it reaches a state + in which one of the two buckets contains the goal amount ''' def two_bucket(bucket_one_cap, bucket_two_cap, desired_liters, first): - if first == "one": - moves = 0 - bucket_one, bucket_two = 0, 0 - while(True): - if bucket_one == 0: - moves += 1 - bucket_one = bucket_one_cap - elif bucket_two == bucket_two_cap: - moves += 1 - bucket_two = 0 - else: - moves += 1 - measure = min(bucket_one, bucket_two_cap - bucket_two) - bucket_one -= measure - bucket_two += measure - if bucket_one == desired_liters: - return (moves, "one", bucket_two) - elif bucket_two == desired_liters: - return (moves, "two", bucket_one) - - elif first == "two": - moves = 0 - bucket_one, bucket_two = 0, 0 - while(True): - if bucket_two == 0: - moves += 1 - bucket_two = bucket_two_cap - elif bucket_one == bucket_one_cap: - moves += 1 - bucket_one = 0 - else: - moves += 1 - measure = min(bucket_two, bucket_one_cap - bucket_one) - bucket_two -= measure - bucket_one += measure - if bucket_one == desired_liters: - return (moves, "one", bucket_two) - elif bucket_two == desired_liters: - return (moves, "two", bucket_one) + sizes = [bucket_one_cap, bucket_two_cap] + goal = desired_liters + goalIndex = 0 if first == 'one' else 1 + + def empty(buckets, i): + return [0, buckets[1]] if i == 0 else [buckets[0], 0] + + def fill(buckets, i): + return [sizes[0], buckets[1]] if i == 0 else [buckets[0], sizes[1]] + + def consolidate(buckets, i): + amount = min(buckets[1 - i], sizes[i] - buckets[i]) + target = buckets[i] + amount + src = buckets[1 - i] - amount + return [target, src] if i == 0 else [src, target] + + def bucket_str(buckets): + return '{},{}'.format(*buckets) + + invalid = [0, 0] + invalid[1 - goalIndex] = sizes[1 - goalIndex] + invalidStr = bucket_str(invalid) + buckets = [0, 0] + buckets[goalIndex] = sizes[goalIndex] + toVisit = [] + visited = set() + count = 1 + while goal not in buckets: + key = bucket_str(buckets) + if key != invalidStr and key not in visited: + visited.add(key) + nc = count + 1 + for i in range(2): + if buckets[i] != 0: + toVisit.append((empty(buckets, i), nc)) + if buckets[i] != sizes[i]: + toVisit.append((fill(buckets, i), nc)) + toVisit.append((consolidate(buckets, i), nc)) + if not any(toVisit): + raise ValueError('No more moves!') + buckets, count = toVisit.pop(0) + + goalIndex = buckets.index(goal) + goalBucket = ['one', 'two'][goalIndex] + otherBucket = buckets[1 - goalIndex] + return (count, goalBucket, otherBucket) diff --git a/exercises/two-bucket/two_bucket_test.py b/exercises/two-bucket/two_bucket_test.py index 0b07d50105..5787ef82c7 100644 --- a/exercises/two-bucket/two_bucket_test.py +++ b/exercises/two-bucket/two_bucket_test.py @@ -25,7 +25,7 @@ def test_bucket_one_size_1_bucket_two_size_3_start_with_bucket_two(self): self.assertEqual(two_bucket(1, 3, 3, "two"), (1, "two", 0)) def test_bucket_one_size_2_bucket_two_size_3_start_with_bucket_one(self): - self.assertEqual(two_bucket(2, 3, 3, "one"), (4, "two", 1)) + self.assertEqual(two_bucket(2, 3, 3, "one"), (2, "two", 2)) if __name__ == '__main__':