A Conversation for The Myth Of 42 [(5-3+0+5) * (6+0) = 42]

42-ism - An automatic solution in Python

Post 1

Krikkit

The Challenge smiley - cake 'Try to solve a H2G2 42-ism in Python'

While watching "Aliens" smiley - ok [Channel-5, 27 July 2004] I decided to knock together a little piece of Python to try and find some more solutions to my own 42-ism. Well, it found two or three for me and I thought 'hold on here be a great 'H2G2 conversation starter'. And hey, there may be similarly minded geeky people out there who might even extend and improve my code!

And what better theme than to use a (free) programming language whose name is inspired by one BBC television program (Monty Python) to solve a problem posed in another (H2G2)!

Anyway, my first Python solution is pasted below. You should be able to run it (with Python 2.2 or later).

Alternatively for A) those that can't program smiley - wah, B) for those who can but don't have Python installed smiley - wah and C) for those who have Python but still can't be bothered smiley - sadface - I've put my program on the web. You can simply enter your researcher number and it will attempt to find a 42-ism for you. It will try 500 times, but don't despair if it fails, just try again. There are a few bugs in the code, maybe you can improve it? And I will probably update it with a more robust and better version soon.

Try the on-line calculator at http://42.kaitak.org

By the way, you can get Python from http://www.python.org
Go on, it's free (and extremely powerful) and see how you get on!

Krikkit.

Python Code Follows...(unfortunately the converstion server will probably remove all te formatting! smiley - erm). If you're really interested contact me and I'll organise a working copy.

# ##############################################################################
# fortytwo.py
# ##############################################################################

"""The Challenge: 'Try to solve a H2G2 42-ism in Python'

While watching "Aliens" [Channel-5, 27 July 2004] I decided to knock together a
little piece of Python to try and find some more solutions to my own 42-ism.
Well, it found two or three for me and I thought 'hold on here be a great
H2G2 conversation starter'. And hey, there may be similarly minded geeky
people out there who might even extend and improve my code!

And what better theme than to use a (free) programming language whose name is
inspired by one BBC television program (Monty Python) to solve a problem
posed in another (H2G2)!

So, was it fun?
Can you improve on this?

By the way, you can get Python from http://www.python.org
Go on, it's free (and extremely powerful) and see how you get on!

Possible Improvements:

- More powerful brackets (i.e how about being able to open
more than one bracket at a time and being more intelligent)
- Extend the operations

R1.00 Using Python 2.3.4
Krikkit (Guide Researcher 801431)
27 July 2004"""

# ##############################################################################
# ##############################################################################
# Import Some Python
# ##############################################################################
import random
import string
import sys

# ##############################################################################
# Function: factorial
# ##############################################################################
def factorial( x ):
"""Python has no built-in factorial.
But it's simple, as presented here without
too much use of the stack..."""

if x < 2:
return 1
f = x
for i in range(2,x):
f *= i
return f

# ##############################################################################
# Function: run
# ##############################################################################
def run( researcherNumber, attempts=500 ):
"""Given a (H2G2) researcher number this function attempts to create an
equation that evaluates to 42. The function can use various operators as
illustrated by H2G2 entry A530560. This routine will finish when a
successful equation has been found (it is returned to the caller as a
string) or the specified number of attempts have been executed
(where a Python None is returned tothe caller).

This version isn't particularly slick (or clever). But it is a bit of
constructive programming fun that another guide author might improve on?"""

# Attempts must be greater than 0
if attempts < 1:
return

# Record length of researcher number
max_digits = len( researcherNumber )
if max_digits > 8:
print "Sorry - your researcher number must be less than"
print "9 characters in length. Hit the browser back button"
print "and try again."
return
elif max_digits == 0:
print "Sorry - your researcher number must have some digits!"
print "Hit the browser back button and try again."
return

# And check the validity -
# i.e. researcher numbers only contain digits
for ch in researcherNumber:
if not ch in string.digits:
print "Sorry, researcher numbers can only contain digits"
print "and yours has a '" + ch + "' in it."
print "Hit the browser back button and try again."
return

# Opertions (in Python syntax) permitted between numbers
# In Python "x**y" raises x to the power y.
# operations = ["*","+","/","-","**"]
operations = ["*","+","/","-"]

# Record our bracket depth.
# Any 'unclosed' brackets at the end of the equation are closed.
bracket_depth = 0

# Keep a record of the equation number
equation_number = 1

# Create a boolean flag which will be used to signal that we've
# found a solution (i.e. a combination of numbers, brackets and
# operations that result in 42. For now we set this to Flase
# so our loop runs until a solution is found or we've run
# out of attempts.
successful = 0

# Initialise our equation (as a string).
# We willpass this back to the caller on success.
# It might end up being "8*0+14*3*1".
equation = ""

# Now start a loop to search for solutions.
# Inside this loop we will set 'successful' to True
# when a solution is found so that the loop finishes.
while not successful:

# Each number (could be combined digits)
number = ""
# Record the digit position (runs 1 to max_digits)
number_index = 1
# Run through each researcher number digit.
# We basically pick a digit (optionally preceeding it
# with a bracket) and then follow the digit by a random
# operation from the operations list.
for digit in researcherNumber:
# Have we opened a bracket before this digit?
bracket_started = 0
# If it's not the last digit
# (possibly) open a single bracket 33% chance
if number_index < max_digits and random.randrange(3) == 0:
equation += "("
number = ""
bracket_depth += 1
bracket_started = 1
# If it's the first digit, optionally add
# an initial "-"? (1 in 6 chance)
if number_index == 1 and random.randrange(6) == 0:
equation += "-"
# Factorial? a 1 in 20 chance...
factorial_started = 0
# if random.randrange(20) == 0:
# equation += "factorial("
# factorial_started = 1
# Build the number...
# Add the current digit to the equation
equation += digit
number += digit
# If we selected a factorial then close it
if factorial_started:
equation += ")"
# Randomly close a bracket (if we have started a bracket).
# But don't close a bracket if we've only got one number
# i.e "(3)" does nothing for us.
if bracket_depth and not bracket_started and random.randrange(2) < 1:
equation += ")"
number = ""
bracket_depth -= 1
bracket_started = 0
# If we haven't just added the last digit
# then insert a random operation
if number_index < max_digits:
if number=="0":
# Numbers cannot begin with "0" - we can only use "0" on
# its own.
# This will be interpreted as an octal (base-8) number.
# i.e. 045 is actually 37. So, if we have a zero we cannot
# choose the "" operation (i.e. we must not append
# another number to a zero)
equation += random.choice(operations)
else:
equation += random.choice(operations + [""])
# Keep digit index up to date
number_index += 1

# We've completed the equation (i.e. used all the numbers)
# so close all unclosed brackets.
while bracket_depth:
equation += ")"
bracket_depth -= 1

# Now try to evaluate the equation -
# remember it could be illegal (i.e. it might have a
# 'divide by zero' in it).
print "%5d" % equation_number + " " + equation + " =",
try:
answer = eval(equation)
print eval(equation)
if answer == 42:
successful = 1
else:
# Reset equation
equation = ""
except:
# Evaluation failed (divide by zero?)
# Nothing to do but go around again!
print "FAIL"
# Reset equation
equation = ""
# Always increment the equation number
# (pass or fail). This way we crudely prevent
# ourselves from getting locked up.
equation_number += 1

# Every equation is an attemp.
# Stop when we've exhausted our allocation.
attempts -= 1
if attempts == 0:
break

# Done - we dropped out of the while-loop...
# so we must have a "42"?
if successful:
print "Forty Two!"
return equation
else:
print "Sorry, no Forty Two"
return

# ##############################################################################
# Entry Point
# ##############################################################################
if __name__ == "__main__":
# We're being executed, not imported
# so run ourselves....
# The user is expected to run this program
# with a single argument i.e. their researcher number.
#if len( sys.argv ) != 2:
# print "ERROR: Missing researcher number."
# print "Usage: fortytwo.py "
# print "e.g.: fortytwo.py 801431"
# sys.exit( 1 )

# Extract the number (second argument)
#researcherNumber = sys.argv[1]
researcherNumber = "801431"
run( researcherNumber, 1000 )


42-ism - An automatic solution in Python

Post 2

Argon0 (50 and feeling it - back for a bit)

Nice one - not programmed in Python, but used it a couple of times....

I'll have a try of this when I get to work...


Key: Complain about this post

Write an Entry

"The Hitchhiker's Guide to the Galaxy is a wholly remarkable book. It has been compiled and recompiled many times and under many different editorships. It contains contributions from countless numbers of travellers and researchers."

Write an entry
Read more