[PYTHON] Sort random FizzBuzz columns with quicksort

Introduction

I learned quicksort last time. The concern was what to do because there are many large and small comparisons. http://qiita.com/cof/items/7b94aac6794d12ae020f

solution

  1. Create a class that associates FizzBuzz with numbers, and overload operators in that class.
  2. Replace the elements of the random column with an instance of the above class.
  3. Quicksort the replaced random columns.

It's faster to completely digitize it once, quickly sort it, and replace it with FizzBuzz later, but as a practice of operator overloading, I created a class that associates FizzBuzz with numbers. reference: http://docs.python.jp/2/reference/datamodel.html#customization

Operator overload

A code that performs an operation on a numerical value (value) associated with a character string (key) and returns a character string or the like corresponding to the resulting key.

def fizzbuzz(n):
  if (n%15) == 0: return 'FizzBuzz'
  elif (n%5) == 0: return 'Buzz'
  elif (n%3) == 0: return 'Fizz'
  else: return n

class FizzBuzzNumber:
  def __init__(self, value):
    self.key = fizzbuzz(value)
    self.value = value

  def __call__(self):
    return self.key

  def __add__(self, other) :
    return fizzbuzz(self.value + other.value)

  def __sub__(self, other):
    return fizzbuzz(self.value - other.value)

  def __mul__(self, other):
    return fizzbuzz(self.value * other.value)

  def __div__(self, other):
    return fizzbuzz(self.value // other.value)

  def __mod__(self, other):
    return fizzbuzz(self.value % other.value)

  def __pow__(self, other):
    return fizzbuzz(self.value ** other.value)

  def __cmp__(self, other):
    return cmp(self.value, other.value)

  def __lt__(self, other):
    return cmp(self.value, other.value) == -1

  def __le__(self, other):
    return cmp(self.value, other.value) in (-1, 0)

  def __eq__(self, other):
    return cmp(self.value, other.value) == 0

  def __ne__(self, other):
    return cmp(self.value, other.value) != 0

  def __gt__(self, other):
    return cmp(self.value, other.value) == 1

  def __ge__(self, other):
    return cmp(self.value, other.value) in (1, 0)

  def __iadd__(self, other) :
    self.value += other.value
    self.key = fizzbuzz(self.value)
    return self

  def __isub__(self, other) :
    self.value -= other.value
    self.key = fizzbuzz(self.value)
    return self

  def __imul__(self, other) :
    self.value *= other.value
    self.key = fizzbuzz(self.value)
    return self

  def __imod__(self, other) :
    self.value %= other.value
    self.key = fizzbuzz(self.value)
    return self

  def __idiv__(self, other) :
    self.value /= other.value
    self.key = fizzbuzz(self.value)
    return self

  def __ipow__(self, other) :
    self.value **= other.value
    self.key = fizzbuzz(self.value)
    return self

When you execute the code below,

fizz = FizzBuzzNumber(3)
buzz = FizzBuzzNumber(5)
print 'fizz + buzz = ', fizz + buzz
print 'fizz - buzz = ', fizz - buzz
print 'fizz * buzz = ',  fizz * buzz
print 'fizz / buzz = ', fizz / buzz
print 'fizz % buzz = ', fizz % buzz
print 'fizz ** buzz = ', fizz ** buzz
print 'fizz > buzz: ', fizz > buzz
print 'fizz < buzz: ', fizz < buzz
print 'fizz == buzz: ', fizz == buzz
print 'fizz != buzz: ', fizz != buzz
print 'fizz <= buzz: ', fizz <= buzz
print 'fizz >= buzz: ', fizz >= buzz
print 'fizz():', fizz()
fizz += buzz
print 'fizz += buzz => fizz() = ' , fizz()
fizz -= buzz
print 'fizz -= buzz => fizz() = ' , fizz()
fizz *= buzz
print 'fizz *= buzz => fizz() = ' , fizz()
fizz /= buzz
print 'fizz /= buzz => fizz() = ' , fizz()
fizz %= buzz
print 'fizz %= buzz => fizz() = ', fizz()
fizz **= buzz
print 'fizz **= buzz => fizz() = ', fizz()

The following result is output.

fizz + buzz =  8
fizz - buzz =  -2
fizz * buzz =  FizzBuzz
fizz / buzz =  FizzBuzz
fizz % buzz =  Fizz
fizz ** buzz =  Fizz
fizz > buzz =  False
fizz < buzz =  True
fizz == buzz:  False
fizz != buzz:  True
fizz <= buzz:  True
fizz >= buzz:  False
fizz(): Fizz
fizz += buzz => fizz() =  8
fizz -= buzz => fizz() =  Fizz
fizz *= buzz => fizz() =  FizzBuzz
fizz /= buzz => fizz() =  Fizz
fizz %= buzz => fizz() =  Fizz
fizz **= buzz => fizz() =  Fizz

Function to quantify

After that, I made a class to quantify FizzBuzz that appeared in a random column.

class FizzBuzzCounter:
  def __init__(self, f_start, b_start, fb_start):
    self.f = f_start
    self.b = b_start
    self.fb = fb_start

  def get_value(self, s):
    if s == 'FizzBuzz': 
      return self.fb
    elif s == 'Buzz': 
      return self.b
    elif s == 'Fizz': 
      return self.f
    else: 
      return s

  def next(self, s):
    if s == 'FizzBuzz': 
      self.fb += 15
    elif s == 'Buzz': 
      if (self.b % 15) == 10:
         self.b += 10
      else:
         self.b += 5
    elif s == 'Fizz': 
      if (self.f % 15) == 12:
         self.f += 6
      else:
         self.f += 3
    else: 
      pass

Functions that replace FizzBuzz columns

Using the above two classes, I created a function that creates a column by replacing the elements of the given FizzBuzz column with an instance of the FizzBuzzNumber class.

def recreate_fizzbuzz_seq(seq):
  counter = FizzBuzzCounter(3,5,15)
  ret = []
  for e in seq:
   ret.append(FizzBuzzNumber(counter.get_value(e)))
   counter.next(e)
  return ret

After that, just give the above new column to the quicksort function created last time.

The quicksort function I made last time

def pivot(target, i, j):
  k = i + 1
  while k <= j and target[i] == target[k]: k += 1
  if k > j: return -1
  if target[i] >= target[k]: 
    return i
  else:
    return k

def partition(target, i, j, x):
  l, r = i, j
  while l <= r:
    while l <= j and target[l] < x: l += 1
    while r >= i and target[r] >= x: r -= 1
    if l > r: break
    target[l], target[r] = target[r], target[l]
    l, r = l + 1, r - 1
  return l

def quick_sort(target,i ,j):
  if i == j: return 
  p = pivot(target, i, j)
  if p != -1:
    k = partition(target, i, j, target[p])
    quick_sort(target, i, k-1)
    quick_sort(target, k, j)

A function that creates a random FizzBuzz column

def make_random_fizzbuzz(start=1,finish=100):
  seq = range(start,finish+1)
  random_fizzbuzz = []
  while seq:
    random_fizzbuzz.append(fizzbuzz(seq.pop(random.randint(0,len(seq)-1))))
  return random_fizzbuzz

Main function

A function that gives a given FizzBuzz column to recreate_fizzbuzz_seq () to create a new column and give the new column to quicksort

def fizzbuzz_sort(target):
  newtarget = recreate_fizzbuzz_seq(target)
  quick_sort(newtarget,0,len(newtarget)-1)
  return newtarget

Start as follows.

fizzbuzz_sort(make_random_fizzbuzz())

Impressions

I'm doing such a silly thing. Also, I think it would have been better for a new instance of FizzBuzzNumber to return __add__ () etc.

Recommended Posts

Sort random FizzBuzz columns with quicksort
Learn quicksort to sort random FizzBuzz columns
Sort names with Python's random module
I tried to sort a random FizzBuzz column with bubble sort.
FizzBuzz with Python3
Quicksort without using sort
Fizzbuzz with exception handling
Sort huge files with python
Browse columns encrypted with sqlalchemy
Bubble sort with fluffy animation