#!/usr/bin/python
# coding=utf-8

from __future__ import with_statement
from glob import glob
from collections import defaultdict
from pprint import pformat

"""
>>> check_fermat(1, 1, 1, 1)
No, that doesn't work.

>>> check_fermat(2, 2, 2, 2)
No, that doesn't work.

>>> rotate_word('A', 3)
'D'

>>> rotate_word('Z', 1)
'A'

>>> rotate_word('cheer', 7)
'jolly'

>>> rotate_word('melon', -10)
'cubed'
"""


# 5.14 Exercise 1:
#
# Fermat’s Last Theorem says that there are no integers a, b, and c such that
#
# a^n + b^n = c^n
#
# for any values of n greater than 2.
#
# Write a function named check_fermat that takes four parameters—a, b, c and
# n—and that checks to see if Fermat’s theorem holds. If n is greater than 2
# and it turns out to be true that a^n + b^n = c^n, the program should print,
# “Holy smokes, Fermat was wrong!” Otherwise the program should print, “No,
# that doesn’t work.”

def check_fermat(a, b, c, n):
    try:
        ai, bi, ci, ni = map(int, (a, b, c, n))
        assert ai == a and bi == b and ci == c and ni == n
        assert n > 2
        assert (ai ** ni) + (bi ** ni) == (ci ** ni)
        print "Holy smokes, Fermat was wrong!"
    except:
        print "No, that doesn't work."

# Write a function that prompts the user to input values for a, b, c and n,
# converts them to integers, and uses check_fermat to check whether they
# violate Fermat’s theorem.

def prompt_user():
    import readline
    ua = raw_input("a>")
    ub = raw_input("a>")
    uc = raw_input("a>")
    un = raw_input("n>")
    check_fermat(ua, ub, uc, un)

#
# 8.13 Exercise 12:
#
# ROT13 is a weak form of encryption that involves “rotating” each letter in a
# word by 13 places*. To rotate a letter means to shift it through the
# alphabet, wrapping around to the beginning if necessary, so ’A’ shifted by 3
# is ’D’ and ’Z’ shifted by 1 is ’A’.  Write a function called rotate_word that
# takes a string and an integer as parameters, and that returns a new string
# that contains the letters from the original string “rotated” by the given
# amount.

def rotate_char(c, n):
    if 'A' <= c and c <= 'Z': return chr((ord(c)+n-ord('A')) % 26 + ord('A'))
    if 'a' <= c and c <= 'z': return chr((ord(c)+n-ord('a')) % 26 + ord('a'))
    return c

def rotate_word(s, n):
    return ''.join(rotate_char(c, n) for c in s)

# For example, “cheer” rotated by 7 is “jolly” and “melon” rotated by -10 is
# “cubed”.
#
#
# You might want to use the built-in functions ord, which converts a character
# to a numeric code, and chr, which converts numeric codes to characters.
#
# Potentially offensive jokes on the Internet are sometimes encoded in ROT13.
# If you are not easily offended, find and decode some of them.
#
# *See wikipedia.org/wiki/ROT13.
#
# [edit] CHALLENGE MODE
#
# This CHALLENGE MODE is slightly unusual, and will require some skills that
# haven't been covered in the text, including file handling, recursion, and
# creative writing.
#
# The problem suggests a few English words that rotate to other English words.
# Using a dictionary file (Linux users will typically find one in
# /usr/share/dict/ or /var/lib/dict/), create a list of such "rotonyms". Don't
# feel limited to ROT13- if you'd rather use a different ROT# scheme (which you
# may find useful for the next bit), please do.
#
# Using this list of words, you will now construct a beautiful poem to be read
# in both its rotated and non-rotated forms. Whoever finishes CHALLENGE MODE
# with the most impressive poem will be awarded The Badger of Honor:

def challenge(dictpath="/usr/share/dict/american-english"):
    words = set()
    results = defaultdict(dict)
    with open(dictpath) as f:
        for line in f:
            words.add(line.strip())
    for w in words:
        for n in range(1, 26):
            r = rotate_word(w, n)
            if r in words:
                results[n][w] = r
    with open("results", "w") as rf:
        rf.write(pformat(results))
    return results


if __name__ == '__main__':
    import doctest
    doctest.testmod()
    challenge()
