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
- Load the data in to a massive string, removing the carriage returns.
- Make a container "Dictionary" for the characters
- Whiz through the massive string using the character as a key and simply adding 1 to the number attached to the key.
- Getting the integer (floor) average (//) for each letter if they were distributed evenly.
- 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.