Skip to content

Commit

Permalink
broken but yolo
Browse files Browse the repository at this point in the history
  • Loading branch information
bshlgrs committed Jul 26, 2016
1 parent f784666 commit bc1414d
Show file tree
Hide file tree
Showing 31 changed files with 707 additions and 267 deletions.
25 changes: 23 additions & 2 deletions README.md
Expand Up @@ -127,11 +127,32 @@ This adds a few complexities.

To start with, it means that I need to have multiple different things in my priority queue: methods both with and without free variables. I might need `forall f: unorderedEach[f]` and also `unorderedEach[:getMax]`

#### other parts


Here's how you make ....?

----

Things to do after this:

- **Data views.** There's a sense in which arrays are naturally
- **Classes.** There's a sense in which arrays are naturally an ordered collection, and BSTs are a sorted collection, and hash maps are a dictionary.
- **Data views.** A list BST is just a BST sorted on insertion order. And you can make views like a histogram view, which can itself be represented by any data structure.
- **More columns.** To some extent, this project looks a lot like implementing a very particular kind of database. Instead of having my lists be pretty much lists of scalars, I could make it work more elegantly for them to look like rows in a database.
- **Code generation.** Generating actual code would be pretty fun.

----------

### Notes on paramaterization

```
reduce[f] if f.commutative <- unorderedEach[_ <- f]
```

implies "If you have an implementation which, for all `g`, can implement `unorderedEach[g]`, you can implement `\forall f if f.commutative: reduce[f]` with the previous implementation applied to `_`.

```
maximum <- reduce[_{commutative} <- 1]
```

imples "If you have an implementation which, for all `g` which are commutative, can implement `reduce[g]`, you can implement `maximum` with the previous implementation applied to `_`.

21 changes: 21 additions & 0 deletions amazing_outcome.md
@@ -0,0 +1,21 @@
# Amazing outcome

If this project went really well, what would it be able to do?

- min stack
- min queue
- Time-travelling key value store
- List with getIndexOfMax
- List with getMax
- Design a data structure that supports the following operations: insert_back(), remove_front() and find_mode(), all in O(1)
- Is there a data structure for key-value pairs that allows insert, update, deletion and finding the minimal value all in log(n)?
- [What data structures support insertion, deletion and selection of a random element with a O(1)O(1) time complexity bound?](https://www.quora.com/What-data-structures-support-insertion-deletion-and-selection-of-a-random-element-with-a-math-O-1-math-time-complexity-bound)
- [How can I design an efficient data structure that supports findMin, findMax, deleteMin, deleteMax, Insert, and delete?](https://www.quora.com/How-can-I-design-an-efficient-data-structure-that-supports-findMin-findMax-deleteMin-deleteMax-Insert-and-delete)
- [What data structures support insertion, deletion and selection of a random element with a O(1) time complexity bound which allow duplicates?](https://www.quora.com/What-data-structures-support-insertion-deletion-and-selection-of-a-random-element-with-a-O-1-time-complexity-bound-which-allow-duplicates)
- [Does a data structure exist which supports logarithmic insertion/removal and constant-time query for the Kth smallest element?](https://www.quora.com/Does-a-data-structure-exist-which-supports-logarithmic-insertion-removal-and-constant-time-query-for-the-Kth-smallest-element)
- What data structure would allow adding an element, removing an element, and querying for the number of elements in the range (a, b), all in O(logn) time?
- [Can I delete an element from the middle of an array using queue in data structures?](https://www.quora.com/Can-I-delete-an-element-from-the-middle-of-an-array-using-queue-in-data-structures)

## Maximally ambitious version

is of course to output actual code.
2 changes: 2 additions & 0 deletions bibliography.md
Expand Up @@ -40,3 +40,5 @@ Pooya Davoodi, [Data Structures: Range Queries and
We present a succinct dynamic data structure that supports traversing low-arity
cardinal trees while answering queries during the traversal.


https://en.wikipedia.org/wiki/Van_Emde_Boas_tree
1 change: 1 addition & 0 deletions big_o_dominance.md
@@ -0,0 +1 @@
How do you know if f(x, y, z) > g(x, y, z)
5 changes: 4 additions & 1 deletion build.sbt
Expand Up @@ -2,6 +2,9 @@ name := "scala_big_o"

version := "1.0"

scalaVersion := "2.11.5"
scalaVersion := "2.11.8"

libraryDependencies += "org.parboiled" %% "parboiled" % "2.1.3"
libraryDependencies ++= Seq(
"com.chuusai" %% "shapeless" % "2.3.1"
)
51 changes: 51 additions & 0 deletions different-kinds.md
@@ -0,0 +1,51 @@
# Different kinds of algorithm problems

## Compose data structures to support a given API quickly

lots, eg

- min stack
- min queue
- Time-travelling key value store
- List with getIndexOfMax
- List with getMax
- Design a data structure that supports the following operations: insert_back(), remove_front() and find_mode(), all in O(1)
- Is there a data structure for key-value pairs that allows insert, update, deletion and finding the minimal value all in log(n)?

### Support a given API of queries which are compositions of simple operations

Eg making indexes for different kinds of queries like `blah.map(f).filter(g).count`

## Graph algorithms

Lots. Lots of things that are basically shortest-path algorithms.

## Dynamic programming on arrays

Build problems out of forall and thereexists and reductions on arrays.

For example:

Find the minimum sum subarray of an array:

array.choose_n_indices(2).minimizeBy((i, j) => array[i..j].sum)

Find the most evenly balanced subarrays of an array:

array.choose_n_indices(3)
.minimizeBy((i, j, k) => abs(array[i..j] - array[j..k]))

Find the amount of water that fills up an array

array.indices.map((i) => {
min(array.take(i).maximize(_), array.drop(i).maximize(_)) - array[i]
}).sum

Incidentally, you can generalize that one to graphs. It looks like this:

graph.nodes.map((node) => {
graph.pathsFromNodeToSet(set(node), boundary).minBy((path) => path.max)
}).sum

Given a histogram, determine the area of the largest rectangle that can be drawn completely within the bounds of the histogram.

10 changes: 10 additions & 0 deletions example.md
@@ -0,0 +1,10 @@
Here's an example of what I want my software to do.

Suppose you want to make a priority queue which lets you read priorities of elements in it.

adt DoublePriorityQueue: Table[unique key, value] {
insert: n
getByUnique[key]: n
getByMinimum[value]: n
}

17 changes: 17 additions & 0 deletions graphs.md
@@ -0,0 +1,17 @@
## Graphs

Graphs are just a data structure. Here are some of their methods:

UnweightedGraph {
nodes
edges
addNode
removeNode
addEdge
removeEdge
edgeWeightFromNode
edgesAtNode
distanceBetweenEdges
}

Lists are just a particular kind of graph.
35 changes: 30 additions & 5 deletions materials/implementations/DataStructures.txt
Expand Up @@ -23,6 +23,24 @@ InvertibleMonoidMemoizer[f] if f.invertible {
insertNextToNode! if f.commutative <- f
}

StackMemoizer[f] {
insertAtEnd! <- f
reduce[f] <- 1
oneSidedRangeQuery[f] <- 1
}

InvertibleSquareRootBlocks[f] if f.invertible {
insertAtEnd! <- 1
updateNode! <- 1
twoSidedRangeQuery[f] <- sqrt(n)
}

SquareRootBlocks[f] {
insertAtEnd! <- 1
updateNode! <- sqrt(n)
twoSidedRangeQuery[f] <- sqrt(n)
}

RedBlackTreeList[f] {
getByIndex <- log(n)
getNext <- 1
Expand All @@ -33,22 +51,29 @@ RedBlackTreeList[f] {
deleteNode! <- 1 + f
deleteBetweenNodes! <- log(n) * (1 + f)
arbitraryRangeQuery[f] <- log(n)
extend! <- log(n) + n
extend! <- n
oneSidedIndexRangeQuery[f] <- log(n)
twoSidedIndexRangeQuery[f] <- log(n)

}

OrderedRedBlackTree[f] {
// ordered by f, memoizing reductions on g
OrderedRedBlackTree[f, g] {
unorderedEach <- n
getNext <- 1
getPrev <- 1
getFirst <- 1
getLast <- 1
updateNode! <- 1
updateNode! <- 1 + g
findFirstBy[f] <- 1
findLastBy[f] <- 1
findKthBy[f] <- log(n)
insertAtIndex! <- log(n)
deleteNode! <- 1
insertAtIndex! <- log(n) + g
getFirstNodeWithValue[f] <- log(n)
deleteNode! <- 1 + g
countBetweenBy[f] <- log(n)
twoSidedValueRangeQuery[g] <- g * log(n)
oneSidedValueRangeQuery[g] <- g * log(n)
}

HistogramHash[f] {
Expand Down
35 changes: 35 additions & 0 deletions materials/implementations/ExampleInput.txt
@@ -0,0 +1,35 @@
adt MaxStack {
insertAtEnd!
getAtEnd
deleteAtEnd!
getMaximumBy[_]
}

adt RangeMinimumQuery {
extend!: 1
twoSidedIndexRangeQuery[1]
}

adt Queue {
insertAtEnd!
getAtStart
deleteAtStart!
}

adt QueueWithRandomDeletion extends Queue {
deleteByIndex!
}

adt SetWithKthSmallest {
setInsert!
setRemove!
getKthSmallest
}

adt ListWithGetIndexOfMin extends List {
getMinimum
}

adt ListWithGetMax extends List {
getMaximum
}
31 changes: 18 additions & 13 deletions materials/implementations/MainImplementations.txt
Expand Up @@ -18,7 +18,8 @@ insertAfterEndNode! <- insertAtEnd!
insertAfterEndNode! <- insertAfterNode!
insertBeforeFrontNode! <- insertBeforeNode!
insertAtFront! <- getFirst + insertBeforeFrontNode!
insertAtIndex! <- getByIndex + (insertAfterNode! | insertBeforeNode!)
insertAtIndex! <- getByIndex + insertAfterNode!
insertAtIndex! <- getByIndex + insertBeforeNode!
insertAfterNode! <- insertNextToNode!
insertBeforeNode! <- insertNextToNode!
extend! <- getLast + insertAfterEndNode! * n
Expand All @@ -34,6 +35,7 @@ deleteNodeWhichIsLast! <- deleteNode!
deleteBetweenNodes! <- n * (deleteNode! + getNext)
deleteAtIndex! <- deleteBetweenNodes!

deleteFirstNodeWithValue! <- getFirstNodeWithValue + deleteNode!

// updates
updateFirstNode! <- getFirst + updateNodeWhichIsFirst!
Expand All @@ -55,16 +57,18 @@ getFirstBy[f] <- getKthBy[f]
getLastBy[f] <- reduce[func{commutative} <- f, _]
getLastBy[f] <- getKthBy[f]
countBetweenBy[f] <- unorderedEach[f]
getMaximum <- getFirstBy[_]
getMinimum <- getLastBy[_]
getMaximum <- getFirstBy[valueOrdering]
getMinimum <- getLastBy[valueOrdering]
deleteMinimumBy![f] <- getMinimumBy[f] + deleteNode!
deleteMaximumBy![f] <- getMaximumBy[f] + deleteNode!
deleteMinimum! <- deleteMinimumBy![_]
deleteMaximum! <- deleteMaximumBy![_]
deleteMinimum! <- deleteMinimumBy![valueOrdering]
deleteMaximum! <- deleteMaximumBy![valueOrdering]
getFirstNodeWithValue[f] <- unorderedEach[f]

// other reductions
count <- unorderedEach[_]
contains <- count
contains <- getFirstNodeWithValue[f]
select[f] <- unorderedEach[f]
reduce[f, zero] <- zero + each[f]
reduce[f, zero] if f.commutative <- zero + unorderedEach[f]
Expand All @@ -74,14 +78,15 @@ mostNumerousEquivalenceClass[f] <- unorderedEach[f]
mostCommonElement <- mostNumerousEquivalenceClass[_]

// eg, querying for the sum of the elements between indexes i and j
twoSidedIndexRangeQuery[f] <- unorderedEach[f]
twoSidedIndexRangeQuery[reduction] <- unorderedEach[reduction]
// eg, querying for the sum of the elements between index 0 and index i
oneSidedIndexRangeQuery[f] <- unorderedEach[f]

// eg, querying for the number of elements whose values are in the range (a, b)
twoSidedValueRangeQuery[f,g] <- unorderedEach[func <- f + g]
// eg, querying for the sum of the k smallest elements
oneSidedValueRangeQuery[f,g] <- unorderedEach[func <- f + g]

oneSidedIndexRangeQuery[reduction] <- unorderedEach[reduction]
minimumRangeQuery <- twoSidedIndexRangeQuery[_]

// // eg, querying for the number of elements whose values are in the range (a, b)
// twoSidedValueRangeQuery[f,reduction] <- unorderedEach[func <- f + reduction]
// // eg, querying for the sum of the k smallest elements
// oneSidedValueRangeQuery[f,reduction] <- unorderedEach[func <- f + reduction]
// oneSidedValueRangeQuery[f,reduction] <- twoSidedValueRangeQuery[func <- f + reduction]

valueOrdering <- 1
3 changes: 2 additions & 1 deletion materials/implementations/scratchpad.txt
Expand Up @@ -2,5 +2,6 @@
addon DoubleStackQueue {
getLast <-> getFirst
insertAtFront! <- insertAtEnd! + deleteFromEnd! // CHECK THIS

deleteFirst! <-> deleteLast!
}
}

0 comments on commit bc1414d

Please sign in to comment.