Can this problem be solved with code?

Came across this book in the attic, today…

Posers: Philip Kaplan: Amazon.com: Books

That’s a representation of the book. I’m not trying to sell or promote it for sale nor do I wish to buy it, it’s right in front of me.

Posers is a book of just that, but none that would take a 130 IQ to solve, just good old common sense and logic. I’m betting there are plenty of posers that can be proven with code, though it is merely hypothesis at this writing.

Take the first poser, which I’m quoting a transcription from the book under Fair Use Guidelines…

A man who wears either blue or brown socks keeps them all in the same drawer in a state of complete disorder. In total there are 20 blue and 20 brown socks in the drawer.

Assuming there is insufficient light for the man to see the color of the socks, how many must he take out of the drawer to be sure that he has a matching pair?

Can this problem be solved with code?

1 Like

Here’s a representation of the poser, and then some more.

1 Like

A little concerned about the literal 3 thrown in there. Must be some way to get around that. Sayin’.

Jotted this down to help me think…

>>> from random import choice
>>> r = ['blue', 'brown']
>>> m = choice(r)
>>> n = choice(r)
>>> o = choice(r)
>>> o == m or o == n
True
>>> 

We need to add the probabilities to get to 1:

P(o == m)  ==  0.5
P(o == n)  ==  0.5

Given there are only two choices, that sums it up. A fifty-fifty chance that it will match one of the pair. So the probability of the next choice matching one of these is 1.

1 Like

New Poser

A game is played by 3 players in which the one who loses must double the amount of money that each of the other 2 players has at that time.
Each of the 3 players loses 1 game and at the conclusion of the 3 games each man has $16.
How much money did each man start with?

Not very elegant, but it works.

class player:
    def __init__(self, name, end_cash):
        self.name = name
        self.cash = end_cash;

    def __str__(self):
        return f'{self.name} has ${self.cash}.00'
    
def reverse_sim_game(players):

    def print_stats():
        for player in players:
            print(player)

    print('After round 3:')
    print_stats()

    for round in range(2, -1, -1):
        print(f'\nAfter round {round}:' if round > 0 else '\nBefore starting the game:')
        players[0 - round].cash += players[1 - round].cash // 2 + players[2 - round].cash // 2
        players[1 - round].cash //= 2
        players[2 - round].cash //= 2
        print_stats()

p1 = player("Player 1", 16)
p2 = player("Player 2", 16)
p3 = player("Player 3", 16)

reverse_sim_game([p1, p2, p3])
Output

After round 3:

Player 1 has $16.00
Player 2 has $16.00
Player 3 has $16.00

After round 2:
Player 1 has $8.00
Player 2 has $32.00
Player 3 has $8.00

After round 1:
Player 1 has $4.00
Player 2 has $16.00
Player 3 has $28.00

Before starting the game:
Player 1 has $26.00
Player 2 has $8.00
Player 3 has $14.00

1 Like

Elegant enough, and nicely done! Didn’t get down to coding but I did build a table and deconstructed the game much as your code has done.

[
  [16, 32, 16, 8],
  [16, 8, 28, 14],
  [16, 8, 4, 26]
]

Built from this sketch…

a3 = 16
b3 = 16
c3 = 16

a2 = 32  # lose
b2 = 8
c2 = 8

a1 = 16
b1 = 28  #  lose
c1 = 4

a0 = 8
b0 = 14
c0 = 26   #  lose
1 Like

Next poser…

If 50 players enter a singles tennis tournament, how many matches are required to determine the winner? Of course, a player is eliminated as soon as they lose a match.

Can this be proven?

>>> def matches(n):
	k = 0
	while n > 1:
		m = n % 2
		n = (n + m) // 2
		k += n - m
	return k

>>> 

Not tough enough? Okay, let’s try this poser…

An automobile has traveled 20000 miles. If 5 tires were used equally in accumulating this mileage, how many miles wear did each tire sustain?

1 Like

3 or 4 wheel car? :wink:
6dd12dc665b899db89a2428761f9be93

1 Like

Good one. Considering this was published in the USA in the 60s when cars were are big as caravans, it would be safe to assume four wheels.

1 Like

Overkill:

class Tire:
    def __init__(self, id, miles=0):
        self.id = id
        self.miles = miles
    def __repr__(self):
        return f'Tire {self.id}: {self.miles}'

class Car:
    def __init__(self, make, model, doors, wheels=4, tires=5, mileage=0):
        self.make = make
        self.model = model
        self.doors = doors
        self.wheels = wheels
        self.tires = [Tire(i, mileage) for i in ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'E')[:tires]]
        self.tires_on_ground = self.tires[:wheels]
        self.spare_tire = self.tires[wheels:] #or spare tires if more than one
        self.mileage = mileage

    def __str__(self):
        return f'''
        Make: {self.make}
        Model: {self.model}
        Number of doors: {self.doors}
        Number of wheels: {self.wheels}
        Number of tires in rotation: {len(self.tires)}
        Miles on each tire: {self.tires}
        Current mileage: {self.mileage}
        '''
    def drive(self, miles_driven):
        self.mileage += miles_driven
        for tire in self.tires_on_ground:
            tire.miles += miles_driven
        
    def rotate_tires(self):
        num_spares = len(self.spare_tire)
        self.tires_on_ground = self.tires[num_spares:]
        self.spare_tire = self.tires[:num_spares]
        self.tires = self.tires_on_ground + self.spare_tire

def simulate_tire_wear(car, miles_to_drive):
    miles_per_rotation = miles_to_drive // len(car.tires)
    while miles_to_drive > 0:
        # print(car) # uncomment to see progression
        car.drive(min(miles_per_rotation, miles_to_drive))
        car.rotate_tires()
        miles_to_drive -= miles_per_rotation
    print(car)

my_truck = Car('Ford', 'F-250', 4)
simulate_tire_wear(my_truck, 20000)

my_bmw = Car('BMW', 'Isetta', 1, 3) # using default 5 tires simulating 2 spare tires
simulate_tire_wear(my_bmw, 20000)
Output

Make: Ford
Model: F-250
Number of doors: 4
Number of wheels: 4
Number of tires in rotation: 5
Miles on each tire: [Tire A: 16000, Tire B: 16000, Tire C: 16000, Tire D: 16000, Tire E: 16000]
Current mileage: 20000

Make: BMW
Model: Isetta
Number of doors: 1
Number of wheels: 3
Number of tires in rotation: 5
Miles on each tire: [Tire A: 12000, Tire B: 12000, Tire C: 12000, Tire D: 12000, Tire E: 12000]
Current mileage: 20000

1 Like

Yeah, but it is cool! On paper it’s just,

5 * a = 4 * 20000
a = 80000 / 5
a = 20000 16000

1 Like

I think you meant a = 16000 (80000 / 5) :wink:

1 Like

D’oh! Yeah, that is what I meant (and what I had on paper) . Will fix it.

1 Like

The jealous husband problem…

Three couples must get across a river using a boat which cannot hold more than 2 people. None of the men will allow his wife to be on the same side of the river or in the boat with any other man (or men) unless he also is present.

Assuming that both the husbands and the wives can row, how do the 3 couples get across under the stated conditions?

1 Like

Worked it out on paper easily enough. Not sure where to even start to code it up. A list of arbitrary moves isn’t really getting the computer to solve the poser. One could code up a game similar to Hanoi Towers, and/or write an algorithm to determine the fewest number of moves to reach the goal.

Figured as much. Okay, this looks like a binary type problem that code might solve…

There are six matches in a horizontal row, 3 with heads up followed by 3 with heads down. The position of the matches can be changed by turning over any 2 adjacent matches.

In 3 moves, show how to change the position of the matches so that the head of the first match is up, the second down, the third up, fourth down, etc.

On paper it is simple enough. Can the logic be written to go from start to finish?

>>> a = int("0b111000", 2)
>>> b = int("0b100000", 2)
>>> c = int("0b101100", 2)
>>> d = int("0b101010", 2)
>>> a, b, c, d
(56, 32, 44, 42)
>>> 56 ^ 24
32
>>> 32 ^ 12
44
>>> 44 ^ 6
42
>>> 
>>> a = int("0b111000", 2)
>>> b = a ^ 8        # the first two bits
>>> a ^= (b >> 1)    # the second two
>>> a ^= (b >> 2)    # the third
>>> a ^= (b >> 3)    # the fourth 
>>> a
42
>>> 

Okay, still fudging around with this one…

>>> def shift_bits(a):
	b = a ^ 8
	while b > 6:
		b >>= 1
		a ^= b
	return a

>>> shift_bits(56)
42
>>>