The Python Challenge – 5

A bit annoyed about this one.  The Peak Hell clue was completely lost on me and in searching I came across another blog that had all the solutions.  I got sucked in and saw what the end game was.  I guess I would have worked it out pretty quickly anyway.

The banner.p name gave it away too I guess. Serialization the python way was easy  enough.

2.7 Solution

#pickle?
import pickle
data = pickle.load( open( "banner.p", "rb" ) )

mycount = 0

for line in data:
myline = ""
for item in line:
counter = 0
mycount = int(item[1])
while counter myline += item[0]
counter += 1
print myline

3.2.3 Solution 

#pickle?
import pickle
data = pickle.load( open( "banner.p", "rb" ) )

mycount = 0

for line in data:
myline = ""
for item in line:
counter = 0
mycount = int(item[1])
while counter myline += item[0]
counter += 1
print (myline)

The Python Challenge – 4

I thought I would write my first python function for this one.  They appear to need to be at the top of the script though with a little casual searching I couldn’t confirm that.

Python 2.7.2 Solution

This got me there but is pretty flaky and needed manually fixing to get to the answer.

import urllib, re
count = 1

def getNextCode(lastCode):
    while True:
        try:
            page = urllib.urlopen('http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s' % lastCode).read()
            code = re.findall('(?<=and the next nothing is )\w*',page)
            print "Code %i is %s.  \nPage message was '%s'.\nPage tried was http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s'.\n" % (count, code[0], page, lastCode)
            return code
        except (IndexError, NameError):
            print "Error: Page message was '%s'\nPage was: http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s'." % (page,lastCode)
            return False
       
nextCode = getNextCode('12345')

count = 1

for count in range (1,400):
        if count == 84:
            nextCode[0] = int(nextCode[0])/2
        nextCode = getNextCode(nextCode[0])

Python 3.2.3 Solution

This deals with the message that you must divide by two when you get 16044 as a code. It also loads the page.  The 3.2.3 has a very different urllib approach.  3.2.3 seems to do crazy stuff with variable types.

import urllib.request, re, webbrowser
count = 1
       
def getNextCode(lastCode):
    while True:
        try:
            if lastCode == '16044': lastCode = str(16044 / 2)
            page = urllib.request.urlopen('http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s' % lastCode).read()        
            code = re.findall(r'(?<=and the next nothing is )\w*',page.decode("utf-8"))
            print ("\nCode %i is %s.\nPage tried was http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s'.\nPage message was '%s'." % (count, code[0], lastCode, page.decode("utf-8")))
            return code
        except (IndexError, NameError):
            print ("Error: Page message was '%s'\nPage was: http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s'." % (page,lastCode))
            return False
     
nextCode = getNextCode('12345')

count = 1

for count in range (1,400):
    if nextCode != False:
        answer = nextCode[0]
        nextCode = getNextCode(nextCode[0])
    else:
        new = 2 # open in a new tab, if possible
        test4url = "http://www.pythonchallenge.com/pc/def/" + urllib.request.urlopen('http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s' % answer).read().decode("utf-8")
        webbrowser.open(test4url,new=new) 
        break
print ("Done.")

The Python Challenge – 3

This one was not so hard.  (Or so I thought).  I could see that it was a regular expression problem right away.  The hardest bit was getting the regex right.

Python 2.7 Solution

import re
data = ''.join([line.rstrip() for line in open('3_message.txt')])
# Looking for the pattern lUUUlUUUl (U = UPPER, l = lower)
regex = r'(?the_answer = re.findall(regex, data)
if len(the_answer) == 1:
    print the_answer[0]
else:
    print "Sorry, your regex is crap.  There were %i matches " % len(the_answer)
    from pprint import pprint
    pprint(the_answer)

But the evil setters were much cleverer than that.  I got:

Sorry, your regex is crap.  There were 10 matches
[‘IQNlQSL’,
 ‘OEKiVEY’,
 ‘ZADnMCZ’,
 ‘ZUTkLYN’,
 ‘CNDeHSB’,
 ‘OIXdKBF’,
 ‘XJVlGZV’,
 ‘ZAGiLQZ’,
 ‘CJAsACF’,
 ‘KWGtIDC’]

This made me sad, even though it was a message to myself.  I pondered the problem and then looked at the middle letters.  They said “linked list”.  wtf?!

I looked up linked lists and was none the wiser.  I then thought I would just try typing linkedlist in to the url, and it worked.  I wonder if Linked Lists are key to the next one.  I rewrote the code so it outputted this.

Better Python 2.7 Solution

import re
data = ''.join([line.rstrip() for line in open('3_message.txt')])
regex = r'(?the_answer = re.findall(regex, data)
print 'You are regex GOD. The answer is %s' % ''.join(word[3] for word in the_answer)

Python 3.2 Solution

import re
data = ''.join([line.rstrip() for line in open('3_message.txt')])
regex = r'(?the_answer = re.findall(regex, data)
print ('You are regex GOD. The answer is %s' % ''.join(word[3] for word in the_answer))

I think I am learning slowly.  But there were about 50 ways of doing this in the solutions and my regex was very basic.  The next one looks pretty basic given my experience with php.

The Python Challenge – 2

This challenge is interesting in that it is confirming to me how inexperienced my programming actually is. I can get to the solution but the answer shows how limited I am. Here is my solution to 2 (I’d copied and pasted the text from the source to a document 2_message.txt.)

My Python 2.7 Solution

# find rare characters in the mess below:

maxoccurence = 1 #how many do I think is rare?

# load up the file
s = open(r"2_message.txt", "r").read()
#find the unique characters
uniqueones = set(s)

#find the rare characters (<= maxoccurence) and their position
rareones = []
for one in uniqueones:
position = []
if s.count(one) <=1:
position.append(one)
position.append(s.index(one))
rareones.append(position)


#rareones is now a multi dimensional list with the character and its position
from operator import itemgetter
solution = ""
for final in sorted(rareones, key=itemgetter(1)):
solution += final[0]
print solution

But here is the first of the suggested solutions

import collections
data = ''.join([line.rstrip() for line in open('2_message.txt')])
OCCURRENCES = collections.OrderedDict()
for c in data: OCCURRENCES[c] = OCCURRENCES.get(c, 0) + 1
avgOC = len(data) // len(OCCURRENCES)
print ''.join([c for c in OCCURRENCES if OCCURRENCES[c] < avgOC])

I want to understand this! So I spend as much time working it out as I do solving the first problem.  This is a great way of learning. I have had to learn what a Dictionary is in python (a sort of associative 2 dimensional array).  Link this to the collections library and you have got something pretty powerful.
The code appears to

  1. Load the data in to a massive string, removing the carriage returns.
  2. Make a container "Dictionary" for the characters
  3. Whiz through the massive string using the character as a key and simply adding 1 to the number attached to the key.  
  4. Getting the integer (floor) average (//) for each letter if they were distributed evenly.
  5. Concatenating all the items in the Dictionary that are less frequent than the average

This is actually not that different to what I did!!!  Just much more efficient.

[c for c in OCCURRENCES if OCCURRENCES[c] < avgOC]

Is very clever.  It is one line that only outputs a string if the occurrences are less than average.  I am still wrapping my head around it.

My Python 3.2.3 Solution

# find rare characters in the mess below:

# official version
import collections
data = ''.join([line.rstrip() for line in open('2_message.txt')])
OCCURRENCES = collections.OrderedDict()
for c in data: OCCURRENCES[c] = OCCURRENCES.get(c, 0) + 1
# avgOC = len(data) // len(OCCURRENCES)
avgOC = 1
print (''.join([c for c in OCCURRENCES if OCCURRENCES[c] == avgOC]) )

This just needed the modification to "Print" though I did find on python 3 it didn't run because there was no collections library.