субота, 28 травня 2016 р.

The Millionth Fibonacci Number in Python

http://www.codewars.com/kata/53d40c1e2f13e331fc000c26/

Description:

The year is 1214. One night, Pope Innocent III awakens to find the the archangel Gabriel floating before him. Gabriel thunders to the pope:
Gather all of the learned men in Pisa, especially Leonardo Fibonacci. In order for the crusades in the holy lands to be successful, these men must calculate the millionth number in Fibonacci's recurrence. Fail to do this, and your armies will never reclaim the holy land. It is His will.
The angel then vanishes in an explosion of white light.
Pope Innocent III sits in his bed in awe. How much is a million? he thinks to himself. He never was very good at math.
He tries writing the number down, but because everyone in Europe is still using Roman numerals at this moment in history, he cannot represent this number. If he only knew about the invention of zero, it might make this sort of thing easier.
He decides to go back to bed. He consoles himself, The Lord would never challenge me thus; this must have been some deceit by the devil. A pretty horrendous nightmare, to be sure.
Pope Innocent III's armies would go on to conquer Constantinople (now Istanbul), but they would never reclaim the holy land as he desired.

In this kata you will have to calculate fib(n) where:
fib(0) := 0
fib(1) := 1
fin(n + 2) := fib(n + 1) + fib(n)
Write an algorithm that can handle n where 1000000 ≤ n ≤ 1500000.
Your algorithm must output the exact integer answer, to full precision. Also, it must correctly handle negative numbers as input.
HINT I: Can you rearrange the equation fib(n + 2) = fib(n + 1) + fib(n) to find fib(n) if you already know fin(n + 1) and fib(n + 2)? Use this to reason what value fib has to have for negative values.

Solution: O(log(n)) implementation of fibonacci using fast doubling 
including negative fibonacci numbers handling

def fib(num): if num >= 0: return fib_helper(num)[0] else: return -fib_helper(-num)[0] if num %2 ==0 else fib_helper(-num)[0] def fib_helper(num): "Helper function for fibonacci()." if num == 0: return (0, 1) elif num == 1: return (1, 1) else: a, b = fib_helper(num // 2) p = a * (2 * b - a) q = b * b + a * a return (p, q) if num % 2 == 0 else (q, p + q)


Another Solution by xcthulhu
def my_fib(n):
  if n < 0: return (-1)**(n % 2 + 1) * fib(-n)
  a,b,p,q = (1,0,0,1)
  while n != 0:
    if (n % 2) == 0:
      (p,q) = (p * p + q * q, (2 * p + q) * q)
      n /= 2
    else:
      (a,b) = ((b + a) * q + a * p, b * p + a * q)
      n -= 1
  return b

Yet Another Fast Solution with memoization

def fib3(n, c={0:1, 1:1}):
    if -1 not in c:
        c[-1], n = -1, n - 1
    if n not in c:
        x = n // 2
        c[n] = fib3(x-1) * fib3(n-x-1) + fib3(x) * fib3(n - x)
    return c[n]

середа, 25 травня 2016 р.

NxN Sudoku Solution Checker

http://www.codewars.com/kata/540afbe2dc9f615d5e000425
Description:
Given a Sudoku data structure with size NxN, N > 0 and √N == integer, write a method to validate if it has been filled out correctly.
The data structure is a multi-dimensional Array, ie:
[
  [7,8,4,  1,5,9,  3,2,6],
  [5,3,9,  6,7,2,  8,4,1],
  [6,1,2,  4,3,8,  7,5,9],

  [9,2,8,  7,1,5,  4,6,3],
  [3,5,7,  8,4,6,  1,9,2],
  [4,6,1,  9,2,3,  5,8,7],

  [8,7,6,  3,9,4,  2,1,5],
  [2,4,3,  5,6,1,  9,7,8],
  [1,9,5,  2,8,7,  6,3,4]
]
Rules for validation
  • Data structure dimension: NxN where N > 0 and √N == integer
  • Rows may only contain integers: 1..N (N included)
  • Columns may only contain integers: 1..N (N included)
  • 'Little squares' (3x3 in example above) may also only contain integers: 1..N (N included)
class Sudoku(): def __init__(self, sudoku): self.board = sudoku def is_valid(self): len_square, len_board = int((len(self.board)) ** 0.5), max(len(i) for i in self.board) set_board = set(range(1, len_board + 1)) #check_size if False in [len(i) == len_board for i in self.board]: return False #check_types if False in [True if type(j)==type(1) else False for i in self.board for j in i]: return False #check_rows if False in [set(i) == set_board for i in self.board]: return False #check_cols if False in [set(i) == set_board for i in zip(*self.board)]: return False checkSquares = [{self.board[i][j] for i in range(y * len_square, y * len_square + len_square) for j in range(x * len_square, x * len_square + len_square)} == set_board for x in range(0, len_square) for y in range(0, len_square)] if False in checkSquares: return False return True


Test Cases:
# Valid Sudoku
goodSudoku1 = Sudoku([
  [7,8,4, 1,5,9, 3,2,6],
  [5,3,9, 6,7,2, 8,4,1],
  [6,1,2, 4,3,8, 7,5,9],

  [9,2,8, 7,1,5, 4,6,3],
  [3,5,7, 8,4,6, 1,9,2],
  [4,6,1, 9,2,3, 5,8,7],
  
  [8,7,6, 3,9,4, 2,1,5],
  [2,4,3, 5,6,1, 9,7,8],
  [1,9,5, 2,8,7, 6,3,4]
])

goodSudoku2 = Sudoku([
  [1,4, 2,3],
  [3,2, 4,1],

  [4,1, 3,2],
  [2,3, 1,4]
])

goodSudoku3 = Sudoku([
  [1]
]);

goodSudoku4 = Sudoku([
  [17, 19, 1, 11, 15, 8, 24, 5, 16, 9, 4, 20, 22, 7, 21, 13, 6, 23, 12, 10, 2, 18, 25, 3, 14],
  [4, 9, 14, 13, 8, 6, 21, 18, 17, 12, 1, 2, 3, 16, 15, 24, 25, 7, 5, 19, 11, 10, 22, 23, 20],
  [24, 25, 7, 21, 12, 4, 1, 2, 20, 3, 13, 5, 23, 10, 11, 9, 22, 8, 18, 14, 15, 19, 16, 6, 17],
  [16, 3, 23, 2, 5, 19, 13, 14, 22, 10, 6, 17, 18, 24, 25, 11, 20, 15, 4, 21, 12, 1, 7, 9, 8],
  [20, 10, 18, 22, 6, 15, 25, 23, 11, 7, 12, 9, 8, 19, 14, 17, 1, 3, 16, 2, 4, 24, 21, 13, 5],
  [19, 6, 20, 5, 25, 18, 2, 16, 15, 21, 17, 8, 7, 9, 23, 4, 12, 10, 14, 1, 24, 3, 11, 22, 13],
  [11, 13, 3, 17, 10, 22, 20, 12, 9, 23, 25, 15, 24, 6, 5, 8, 2, 18, 19, 16, 21, 4, 1, 14, 7],
  [15, 24, 9, 18, 21, 10, 7, 3, 4, 5, 14, 1, 11, 2, 16, 20, 13, 17, 23, 22, 6, 25, 19, 8, 12],
  [14, 7, 16, 12, 2, 1, 17, 19, 6, 8, 21, 22, 4, 18, 13, 3, 24, 25, 15, 11, 10, 20, 23, 5, 9],
  [8, 23, 22, 1, 4, 24, 11, 25, 13, 14, 3, 12, 10, 20, 19, 5, 9, 21, 7, 6, 18, 16, 2, 17, 15],
  [12, 1, 5, 10, 24, 2, 3, 21, 14, 11, 15, 25, 6, 22, 17, 16, 8, 9, 13, 4, 20, 23, 18, 7, 19],
  [23, 21, 2, 3, 17, 13, 12, 10, 7, 4, 8, 18, 19, 5, 9, 25, 15, 1, 20, 24, 22, 14, 6, 16, 11],
  [18, 8, 11, 20, 14, 16, 9, 17, 25, 1, 24, 21, 12, 4, 7, 6, 19, 22, 2, 23, 13, 5, 15, 10, 3],
  [6, 22, 25, 19, 13, 5, 8, 20, 18, 15, 23, 3, 16, 1, 2, 21, 11, 14, 10, 7, 9, 17, 12, 4, 24],
  [9, 16, 4, 15, 7, 23, 6, 22, 24, 19, 10, 11, 13, 14, 20, 18, 17, 5, 3, 12, 25, 21, 8, 2, 1],
  [7, 2, 13, 9, 20, 17, 16, 11, 21, 22, 18, 24, 14, 23, 1, 15, 3, 6, 25, 5, 8, 12, 10, 19, 4],
  [22, 18, 19, 24, 16, 3, 4, 8, 12, 25, 5, 13, 17, 15, 6, 10, 7, 11, 1, 9, 14, 2, 20, 21, 23],
  [5, 12, 6, 4, 1, 20, 18, 15, 23, 24, 16, 10, 2, 21, 3, 22, 14, 19, 8, 13, 7, 9, 17, 11, 25],
  [25, 17, 8, 14, 3, 7, 10, 13, 1, 2, 20, 19, 9, 11, 22, 12, 23, 4, 21, 18, 16, 15, 5, 24, 6],
  [10, 15, 21, 23, 11, 14, 19, 9, 5, 6, 7, 4, 25, 12, 8, 2, 16, 24, 17, 20, 1, 13, 3, 18, 22],
  [3, 11, 24, 7, 18, 9, 23, 1, 8, 13, 19, 16, 21, 17, 12, 14, 10, 20, 22, 25, 5, 6, 4, 15, 2],
  [13, 14, 15, 25, 19, 21, 22, 4, 10, 18, 2, 6, 1, 3, 24, 23, 5, 12, 11, 8, 17, 7, 9, 20, 16],
  [2, 4, 17, 16, 9, 11, 15, 7, 19, 20, 22, 14, 5, 25, 10, 1, 18, 13, 6, 3, 23, 8, 24, 12, 21],
  [21, 20, 12, 8, 22, 25, 5, 6, 3, 16, 9, 23, 15, 13, 18, 7, 4, 2, 24, 17, 19, 11, 14, 1, 10],
  [1, 5, 10, 6, 23, 12, 14, 24, 2, 17, 11, 7, 20, 8, 4, 19, 21, 16, 9, 15, 3, 22, 13, 25, 18]
])


# Invalid Sudoku
badSudoku1 = Sudoku([
  [0,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9],
  
  [1,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9],
  
  [1,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9]
])

badSudoku2 = Sudoku([
  [1,2,3,4,5],
  [1,2,3,4],
  [1,2,3,4],  
  [1]
])

badSudoku3 = Sudoku([
  [2]
])

badSudoku4 = Sudoku([
  ['']
])

badSudoku5 = Sudoku([
  [0]
])

badSudoku6 = Sudoku([
  [True]
])

badSudoku7 = Sudoku([
  [1,4,4,3,'a'],
  [3,2,4,1],
  [4,1,3,3],
  [2,0,1,4],
  ['',False,None,'4']
])

badSudoku8 = Sudoku([ 
  [1,2,3, 4,5,6, 7,8,9], 
  [2,3,1, 5,6,4, 8,9,7], 
  [3,1,2, 6,4,5, 9,7,8], 
  [4,5,6, 7,8,9, 1,2,3], 
  [5,6,4, 8,9,7, 2,3,1], 
  [6,4,5, 9,7,8, 3,1,2], 
  [7,8,9, 1,2,3, 4,5,6], 
  [8,9,7, 2,3,1, 5,6,4], 
  [9,7,8, 3,1,2, 6,4,5]
])