Skip to content

payes/fun-with-programming

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fun With Programming

ABC - Always Be Coding

  • Practice programming and keep your brain sharp

Visualize Z Array

Txt     a   a   a   a
Txt     a   a   a   a
Z       x   3   2   1         // Dont bother about x

Txt     a   b   a   b
Txt     a   b   a   b
Z       x   0   2   0         // Dont bother about x

Txt     a   b   c   d
Txt     a   b   c   d
Z       x   0   0   0         // Dont bother about x
DP Formula               From Past / Previous Occurences
DP & Past                Think loop or nested loops & memo

f(n) ~ f(n-1)
f(x,y) ~ f(x-1,y-1) + f(x,y-1) + f(x-1,y)
DP Formula                Neighbours Derived from Center
DP & Neighbours           Is BST

f(x+1,y) ~ f(x,y)         Bottom    ~ Neighbour
f(x-1,y) ~ f(x,y)         Top       ~ Neighbour
f(x,y-1) ~ f(x,y)         Left      ~ Neighbour
f(x,y+1) ~ f(x,y)         Right     ~ Neighbour
var p$t = fmt.Sprintf(%s$%s, pattern, txt)

z = ZArrayOf(p$t)

for i:=0; i<len(z); i++ {
  if z[i] == len(P) {
    return "P found in T"
  }
}
MinHeapify(Array, Pant) {
  Min(L, P, R)
  if MinNePant() {
    Swap arr[min], arr[pant]
    reCurse(arr, min)
  }
}

MinHeapify(arr []int, p int) {
  var l := 2*p + 1
  var r := 2*p + 2
  var min = p

  if l <= len(arr) && arr[l] < arr[min] {
    min = l
  }
  if r <= len(arr) && arr[r] < arr[min] {
    min = r
  }
  if min != p {
    arr[min], arr[p] = arr[p], arr[min]
    MinHeapify(arr, min)
  }
}
fmt.Print("When DP & Recursion")
fmt.Print("           Think What Base Value To Return")
fmt.Print("           When to return 0 or 1 etc.")

fmt.Print("When DP & Recusion & Min / Max")
fmt.Print("           Max of all Combinations OR")
fmt.Print("           Min of all Combinations")
fmt.Print("           Double Check before Invoking A Combination")
fmt.Print("           Adding Condition before Invoking Might Be Wrong")
// Given:             str1 & str2
// Find:              Minimum No of Operations to Transform str1 to str2
// Assumptions:       Insert, Delete & Replace are Valid Operations

// Samples:
//                    amit & asmit
//                    amit & samit
//                    amit & amits

fmt.Print("Traverse Both Strings Together")
fmt.Print("Either From Left to Right or Vice-Versa")

// --
// O(3^N) runtime
//
// Optimise further via:
//                        1/ memoization
//                        2/ for loop instead of recursion
// --
func FindMinOps(str1, str2 string) int {
  if len(str1) == 0 {
    return len(str2)
  }
  if len(str2) == 0 {
    return len(str1)
  }

  m := len(str1)
  n := len(str2)

  if str1[m-1] == str2[n-1] {
    return findMinOps(str1[:m-1], str2[:n-1])   // EQUALS -- i.e. 0 Add
  }

  // ---
  // BELOW IS WRONG !! DONT ADD CONDITIONS !!
  // ---
  //  var i, r, d int
  //  if m < n {
  //    i = findMinOps(str1[:m], str2[:n-1])        // INSERT
  //  } else if m == n {
  //    r = findMinOps(str1[:m-1], str2[:n-1])      // REPLACE
  //  } else {
  //    d = findMinOps(str1[:m-1], str2[:n])        // DELETE
  //  }

  return 1 + Minimum(                               // Add 1 Else Its 0 Always
    findMinOps(str1[:m], str2[:n-1]),
    findMinOps(str1[:m-1], str2[:n-1]),
    findMinOps(str1[:m-1], str2[:n]),
  )
}
// Given:             [1, 3, 5]
// Calc:              No. of ways to form N from given items
// Assumption:        Repetitions Allowed
// Assumption:        Every Order is Unique

fmt.Print("           Derive the Formula First Then Logic")
fmt.Print("           Should Formula Use 1, 3 & 5")
fmt.Print("           Wrong Way of Thinking")

fmt.Print("How many ways to get:")
fmt.Print("                     N=1")
fmt.Print("                     N=2")
fmt.Print("                     N=3")

fmt.Print("No Need To Find All Answers")
fmt.Print("Just Ways To Find Smallest States")
fmt.Print("Use Known Ways as Conditions")

fmt.Print("How Many Ways to Get N=4")
fmt.Print("                     Add 3 to Ways_to_Get(1)")
fmt.Print("                     Add 1 to Ways_to_Get(3)")
fmt.Print("                     Add 5 to Ways_to_Get(0)")

fmt.Print("                     Add X where X is an Arr Item")
fmt.Print("                     Ways(Y) where Y is SMALL & CAN BE CALC easily")

fmt.Print("TIP:                 X = Each Item = Treated Exclusively")
fmt.Print("TIP:                 Y = Target / Final State = SMALL & KNOWN")

fmt.Print(Formula:              f(4) = f(1) + f(3) + f(0)")
fmt.Print(                      i.e. f(n) = f(n-3) + f(n-1)")

fmt.Print("How Many Ways to Get N=6")
fmt.Print("                     Add 3 to Ways_to_Get(3)")
fmt.Print("                     Add 1 to Ways_to_Get(5)")
fmt.Print("                     Add 5 to Ways_to_Get(1)")

fmt.Print("Formula:             f(6) = f(3) + f(5) + f(1)")
fmt.Print("                     i.e. f(n) = f(n-3) + f(n-1) + f(n-5)")

fmt.Print("Conditions:")
fmt.Print("1/                   if n < 1 return 0")
fmt.Print("2/                   if n == 1 return 1")
fmt.Print("Correct Formula:     f(n) = f(n-3) + f(n-1) + f(n-5)")
fmt.Print("Shortest Path:         May Have Optimal Sub-Structure Property")
fmt.Print("                       i.e. a Combination of Shortest Paths")

fmt.Print("Longest Path:          DoNot Have Optimal Sub-Structure Property")
// Given:                 Level Order Traversal of a Binary Tree
// Check:                 Is BinaryTree A MinHeap?
func IsMinHeap(arr []int) bool {
  size := len(arr)
  for parent:=(size-2)/2; parent>=0; parent-- {
    l := 2*parent + 1
    r := l + 1
    if l < size && arr[parent] > arr[l] {
      return false
    }
    if r < size && arr[parent] > arr[r] {
      return false
    }
  }
  return true
}
fmt.Print("Binary Heap:        Single Tree")
fmt.Print("Binomial Heap:      Collection of Trees")
fmt.Print("Fibonacci Heap:     Collection of Trees of Any Shape")

fmt.Print("Fibonacci Heap Property:")
fmt.Print("                    All trees' root are connected")
fmt.Print("                    Roots are connected via Circular Doubly Linked List")
fmt.Print("Heap to Array:              Level Order Traversal")
fmt.Print("Heap to Array:              Zig Zag")

fmt.Print("Del Min from Min Heap:      Remove & Heapify from Root")
fmt.Print("Delete from Min Heap:       Replace the Val with MAX_MIN then DelMin")
fmt.Print("Heapify:                    A recursive approach")
fmt.Print("Heap Conditions:            l, r <= size & parent >= 0")
fmt.Print("Heap Parent Idx:")
fmt.Print("=                   (childIdx-1)/2")
fmt.Print("=                   (len(arr)-2)/2")
fmt.Print("=                   len(arr)/2 - 1")
fmt.Print("Heap QnA")

fmt.Print("Q:     How to Ensure Lower SubTrees are Always Heapified?")
fmt.Print("A1:    Start from Bottom Parent & Call Heapify (a recursive func)")
fmt.Print("A2:    i.e. Loop In Reverse Order")
fmt.Print("A3:    i.e. Loop from Bottom Parent To Root")

fmt.Print("Q:    Why Leaf Nodes Dont Need to be Heapified?")
fmt.Print("A:    Leaf Nodes Always Follow Heap property")
// ----
// Given the root index heapify the tree recursively
//
// Assumption:        subtrees are already heapified
// Aliter:            use func instead of method
// Aliter:            use []int instead of *MinHeap
// ----
func (m *MinHeap) MinHeapify(parent int) {
  // ---
  // Deal with indexes
  // Since goal is to swap the array in-line
  // ---
  var l = m.Left(parent)
  var r = m.Right(parent)

  var smallest = parent

  if l < m.Size && m.Items[l] < m.Items[smallest] {
    smallest = l
  }
  if r < m.Size && m.Items[r] < m.Items[smallest] {
    smallest = r
  }
  if smallest != parent {
    // swap
    m.Items[parent], m.Items[smallest] = m.Items[smallest], m.Items[parent]

    // ---
    // given index val was swapped
    //
    // heapify till it finds its right position
    // ---
    m.MinHeapify(smallest)
  }

  // If No Change then No Recursion
  // Since SubTrees are ASSUMED to be Heapified
}
// --
// Pure Function
// --
func MaxHeapify(arr []int, parent, size int) {
  var l := 2*parent+1
  var r := 2*parent+2

  var largest = parent

  // --
  // Compare both Left & Right against Parent
  // --
  if l <= size && arr[l] > arr[largest] {
    largest = l
  }
  if r <= size && arr[r] > arr[largest] {
    largest = r
  }
  if largest != parent {
    // --
    // Array is the Heap
    // No extra struct
    // --
    arr[parent], arr[largest] = arr[largest], arr[parent]

    // --
    // Recurse due to new largest
    // --
    MaxHeapify(arr, largest, size)
  }
}
// --
// Convert MinHeap to MaxHeap in O(N)
//
// Tip:     Loop from "Bottom Parent" to "Root" & MaxHeapify
// Note:    Ignore the leaves
// Note:    This seems O(NlogN) but its O(N). HOW?
// --
func MinHeapToMaxHeap(arr []int) {
  // --
  // pIdx =(cIdx-1)/2, OR
  // pIdx =(size-2)/2
  // --
  size := len(arr)

  for i:=(size-2)/2; i>=0; i-- {
    MaxHeapify(arr, i, size)
  }
}
// --
// O(NlogN) ~ O(N) - HOW?
// --
func BuildHeap(arr []int) {
  if len(arr) == 0 {
    return nil
  }

  size = len(arr)
  for i:=(size-2)/2; i>=0; i-- {  // N
    Heapify(arr, i)               // logN
  }
}
fmt.Print("Anagrams relevant to encode & decode")
fmt.Print("Ana enD")
fmt.Print("Sum of at-least 2 numbers is k or n*k")
fmt.Print("Above Is Same As Sum of at-least 2 numbers % k == 0")

fmt.Print("(a + b)%k == 0 if (a%k + b)%k == 0")
fmt.Print("If Above Then (c + a + b)%k == c%k Since (a + b)%k == 0")

fmt.Print("When Programming Use map[int]int{0: -1} & Condition")
fmt.Print("Map's Key = 'Current Sum' & Value = 'Idx of Number In Array'")
fmt.Print("2D Graph - graph [][]int")
fmt.Print("hasEdge:   graph[u][v] == 1")
fmt.Print("If BiPartite Graph")
fmt.Print("Then Red Blue Color Scheme @ Each Level")
fmt.Print("Visualize Graph as a Tree")
fmt.Print("If Node is Blue Then Its Neighbours in Red")
fmt.Print("If Node is Blue Then Its Neighbours' Neighbours in Blue")
fmt.Print("BiPartite Graph")
fmt.Print("All Edges Joining Vertices belonging to 2 Independent Sets")
fmt.Print("If BPG[u][v] == 1 then u & v must be in different sets")
fmt.Print("BiPartite Color Store")
fmt.Print("colors []int - colors[u] = -1 or 0 or 1")
fmt.Print("-1=no_color, 0=red, 1=blue")
fmt.Print("Graph as 2D array vs. Adjacency List")
fmt.Print("Graph as 2D Array gives O(v^2) in BFS & other calculations")
fmt.Print("Graph as Adjacency List gives O(v+e) in BFS")
fmt.Print("Adjacency List == Sparse Graph == Space Efficient")
fmt.Print("When Array of strings Then 2D Array Already")
fmt.Print("When Alien Dictionary And Order of Chars is Given")

func OrderedAccess(order string) []int {
  var res = make([]int, 26)   // assume 26 is the max order
  for i, c := range order {
    res[c] = i                // notice the reverse store
  }
  return res
}
fmt.Print("When 'for loop' & use of '++' & lots of 'break' or 'continue'")
fmt.Print("Then better use 'for i:=0; i < size; i++' loop")
fmt.Println("Dependency calculations use Topological Sort")
fmt.Println("Dictionary")
fmt.Println("Compilation of dependent programs")

fmt.Println("A depends on B & B depends on C")
fmt.Println("Then in Topological Sort: [C, B, A]")
fmt.Println("Ulta Topi")
// ---
// EXTRA ELEMENTS CREEP IN; AVOID
// ---
var sarr = make([]int, len(arr))
for _, i := range arr {
  sarr = append(sarr, i)
}

// ---
// EXTRA ELEMENTS CREEP IN; AVOID
// ---
var sarr = make([]int, len(arr))
sarr = append(sarr, arr...)

// ---
// SIMPLE OLD STYLE COPY; GOOD
// ---
var sarr = make([]int, len(arr))
for idx, elem := range arr {
  sarr[idx] = elem
}
// Terse; Is It Safe?
func msort(given []int) []int {
  if len(given) == 1 {
    return given
  }

  mid := int(len(given)/2)
  left := given[0:mid]
  right := given[mid:]

  return merge(msort(left), msort(right))
}

// Vs.

// Verbose & Tricky But Perhaps Safer
func msort(given []int) []int {
  size := len(given)
  if size == 1 {
    return given
  }

  mid := int(size/2)
  var left = make([]int,mid)
  var right = make([]int,size-mid)    // WATCH OUT

  for idx, item := range given {
    if idx < mid {
      left[idx] = given[idx]
    } else {
      right[idx-mid] = given[idx]     // WATCH OUT
    }
  }

  return merge(msort(left), msort(right))
}
str[idx]        // bytes
rune(str[idx])  // rune
str[left:right+1] // SUBSTRING; LEFT & RIGHT INCLUDED
str[left:right]   // RIGHT EXCLUDED
// map[int]bool as seen
// map[rune]bool as seen

// TIP
// WHEN TO RESET
// RESET TO WHAT?
// - EMPTY?
// - SINGLE ELEMENT?
// - CURRENT ELEMENT?
// ^ IS NOT POWER
// ^ IS XOR
// ^ IS BITWISE XOR OPERATOR FOR INTEGERS
// rune is an alias for int32
fmt.Println("RUINED INTERNATIONAL MAN")
// byte is an alias for unit8
fmt.Println("BYE TO UNIFY")
// unit ; all positive numbers including 0
// uint ranges from 0 to 4294967295
// int ranges from –2147483648 to 2147483647
// MAX INT = HALF OF MAX UNIT
// MIN INT = -(HALF OF MAX UNIT) - 1

var MinUint uint = 0
var MaxUint uint = ^MinUint         // all ones

// Divide by 2
// i.e. arithmetic right shift
var MaxInt int = int(MaxUint >> 1)  // all ones except high bit

// Either ^MaxInt
// OR -MaxInt-1
var MinInt int = ^MaxInt            // all zeros except high bit

fmt.Println("TRY TO EAT BUFFET. YOU CAN'T. YOU END UP DIVIDING BY HALF")
fmt.Println("BUFFET EATS YOU. HE CAN. HIS MONEY GETS DOUBLED I.E. 2X")
// ARRAY MUTATION

size := len(arr)    // SOME ARRAY
top := arr[size-1]  // TOP IS LAST ELEMENT
arr = arr[:size-1]  // REMOVE LAST ELEM
// BST ITERATOR - O(h) space - h is tree's height

// STORE ROOT && THEN LEFT NODES(s)
// I.E. STORE IN DESC ORDER
// IS ENOUGH TO PROVIDE ENTIRE TREE AS INORDER LIST
// NEXT() LOGIC IS TEASER

type BSTIter struct {
  Stack []*BST
}

// ---
// push is the teaser function that
// helps you build a BST with O(h) space
// ---
func (i *BSTIter) push(b *BST) {
  tmp := b
  for tmp != nil {
    // -------------------
    // Store in DESC order
    // -------------------
    i.Stack = append(i.Stack, tmp)
    tmp = tmp.Left // JUST THE LEFT
  }
}
// Product of Array Items Excluding Current

// --------
// HINT:
// --------
// - Loop 1 - L to R
// - Product All Lefts i.e. Already Seen Items
// - Loop 2 - R to L
// - Product All Rights i.e. Already Seen Items

// - Use a New Array that Stores Above Product
// - Loop 1 - Arr[idx] = Current Left Product
// - Loop 2 - Arr[idx] = Arr[idx] * Current Right Product

// TIP - Product Excluding Self is Two loops Two Directions Solution
// Diameter of Binary Tree is all about maximums
// Having a maximum func helps a lot

func maximum(a, b int) int {
  if a > b {
    return a
  }
  return b
}
// MaxSumPath of BinaryTree is mad about max
// Avoid initialising to Min Int etc

func maximum(first int, others ...int) int {
  var max = first
  for _, i := range others {
    if max < i {
      max = i
    }
  }
  return max
}

References

clojure style guide has inspired this styling

People

About

ABC - Always Be Coding

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages