Commit graph

1519 commits

Author SHA1 Message Date
William Carroll
c6f6d5f33b Fix typo
It's Splitwise... not Transferwise!
2020-12-07 20:10:33 +00:00
William Carroll
9549dbb266 Update BFS impls
I've subtly been implementing breadth-first traversals in graphs
incorrectly. The change is subtle, but updating `seen` needs to happen
immediately after queuing an item.

The results will remain the same, but the runtimes will differ dramatically. I
didn't notice this until I attempted to complete LeetCode's "count islands"
challenge, and LeetCode rejected my solution because it could not finish before
timing out. After looking at other candidates' solutions and comparing them to
mine, I couldn't see any difference... except for this subtle difference.

This SO answer provides a helpful explanation:
https://stackoverflow.com/questions/45623722/marking-node-as-visited-on-bfs-when-dequeuing

The take-away lesson here is to always call `seen.add(..)` immediately after
enqueuing.
2020-11-23 23:21:20 +00:00
William Carroll
c00eed469c Solve "cafe order checker" (again)
Perhaps my fifth iteration of solving this problem.
2020-11-21 16:31:53 +00:00
William Carroll
6ccdb06717 Solve "permutation palindrome" (again)
Python's `collections` library really shines for this problem.
2020-11-21 16:24:14 +00:00
William Carroll
60d7ea5b91 Implement a queue using two stacks
The space cost is O(n). The runtime cost of enqueue is O(1); the runtime cost of
dequeue is O(n). Using the "accounting method", the cost of an item in the
system is O(1). Here's why:

+------------+----------------------------+------+
| enqueue    | push onto lhs              | O(1) |
+------------+----------------------------+------+
| lhs -> rhs | pop off lhs; push onto rhs | O(1) |
+------------+----------------------------+------+
| dequeue    | pop off rhs                | O(1) |
+------------+----------------------------+------+
2020-11-21 16:15:43 +00:00
William Carroll
417d3b5fff Implement a bottom-up fibonacci
The bottom-up solution run in O(n) time instead of O(2^n) time, which the
recursive solution runs as:

```
def fib(n):
    return fib(n - 2) + fib(n - 1)
```

Remember that exponential algorithms are usually recursive algorithms with
multiple sibling calls to itself.
2020-11-21 14:48:12 +00:00
William Carroll
70e74a4027 Solve "linked-list-cycles"
Write a predicate for checking if a linked-list contains a cycle. For additional
practice, I also implemented a function that accepts a linked-list containing a
cycle and returns the first element of that cycle.
2020-11-21 14:47:18 +00:00
William Carroll
cbdac30643 Reimplement bst-checker
Practice makes perfect. See the previous commit for a more details about this
solution.
2020-11-21 14:21:05 +00:00
William Carroll
2b5bbb98ca Refactor existing bst-checker implementation
I believe the previous solution is invalid. This solution works and it should be
more time and space efficient.

Space-wise our stack grows proportionate to the depth of our tree, which for a
"balanced" BST should be log(n). Doing a BFT on a BST results in memory usage of
n because when we encounter the leaf nodes at the final level in the tree, they
will be 1/2 * n for a balanced BST.
2020-11-21 14:14:50 +00:00
William Carroll
1dc6695a47 Solve merge-sorted-arrays (again)
InterviewCake.com has a section on Facebook's interview, so I'm attempting to
solve all of the problems on there even if that means I'm resolving
problems. The more practice, the better. Right?

URL: interviewcake.com/facebook-interview-questions
2020-11-21 13:41:33 +00:00
William Carroll
0ccaa22032 Solve "find duplicate" using a graph
This problem is unusually difficult, but the solution is elegant.
2020-11-21 13:35:05 +00:00
William Carroll
847aad2a14 Implement the Levenstein "edit distance" algorithm
This is the mother of dynamic programming algorithms in my opinion. It computes
the minimal "edit distance" between two input strings where an edit is
considered one of:
  - inserting a character into `a`
  - deleting a character from `a`
  - substituting a character in `a` with a character from `b`

It took me awhile to grok the algorithm, but I implemented this from my
understanding of something that I read ~3 nights prior, so I must've understood
what I read. Good news!
2020-11-20 21:59:18 +00:00
William Carroll
f652ea0be6 Solve "count islands" problem
This morning, I attended the "Interview Club" and was asked this question by the
interviewer in front of ~20 FTEs. While I struggled to fully solve it during the
abridged (i.e. 20 minute) timeslot, I completed the problem afterwards.

Here is my solution.
2020-11-20 21:32:22 +00:00
William Carroll
fa717e8a6f Re-implement suffix_tree function
Create a suffix tree from an input string. This implementation uses a stack to
control the flow of the program.

I expected this attempt to be easier than my first attempt, but surprisingly, it
was similarly difficult. It took me ~30-45 minutes to successfully implement
this function, and I'm still not pleased with the final result.
2020-11-19 21:12:36 +00:00
William Carroll
1088e4143d Implement a suffix tree
While it took me awhile to implement, this exercise was definitely worth
doing. I think there should be a more elegant way to construct the tree using
maybe a stack, but I couldn't find it.

All of this was part of a larger effort to search a string for a variety of
patterns. The solution is to compile the string into a suffix tree and then
search the suffix tree for each of the patterns.

I'm glad I didn't gloss over this exercise.
2020-11-19 00:35:23 +00:00
William Carroll
c0268ed31a Refactor random-choice
Prefer initializing `result` to an empty array of size `m`, which makes the
algorithm a bit more elegant.
2020-11-17 23:54:54 +00:00
William Carroll
751b5327a9 Solve algorithms dealing with randomness
Tonight I learned that random sample where each element in the sampling corpus
has an equal likelihood of being chosen is a brand of algorithms known as
"reservoir sampling".

- Implement random.shuffle(..)
- Implement random.choice(..)

Surprisingly, candidates are expected to encounter problems like this during
interviews.
2020-11-17 22:28:24 +00:00
William Carroll
572fb0fe5f Solve "nearby words" function
Given an input like "gello" suggest an correction like "hello".

This is a proof-of-concept problem for writing a simplistic auto-correction
algorithm for a mobile device.
2020-11-16 17:17:28 +00:00
William Carroll
6989c3a91a Implement the Rabin Karp string matching algorithm
This algorithm is pretty interesting because it runs in linear time with respect
to the length of the `corpus` string. It does this by using a sliding window
hash. This hash -- because it's a sliding window -- runs in constant time for
each iteration; we're only adding and subtracting one character each time and
not re-hashing the whole "window".

When our hashes match, only then do we compare the "window" to the
`pattern`. String comparisons are linear because they compare each character to
each character one at a time. But because we only compare strings when are
hashes match (a check which runs in constant time), this spares us the
performance hit.
2020-11-16 17:14:08 +00:00
William Carroll
a2fa88f561 Prefer mutative variant of delete for HashTable
Instead of calling `filter(..)`.
2020-11-16 17:13:39 +00:00
William Carroll
a457a81bbb Add another solution to the "move zeroes to end" problem
Support the optimally performance solution of which I'm aware.
2020-11-16 17:13:03 +00:00
William Carroll
ff08b723db Solve "find pairs for sum"
I have encountered this problem 3x in the wild thus far:
  1. www.InterviewCake.com
  2. Cracking the Coding Interview
  3. www.Pramp.com
2020-11-16 17:12:05 +00:00
William Carroll
92ab94943e Start working on the "Hard" problems
Firstly, implement a function that adds two arguments together... without using
the `+` operator. I need to drill this problem. Thankfully I took a Coursera
course that taught me how to make a half-adder and a full-adder, but the
recommended solution for this is a bit more difficult.
2020-11-16 17:10:57 +00:00
William Carroll
30f4d6f4a4 Implement a simple hash function and hash table
I was always curious how hashing functions were implemented, so I read about the
"polynomial rolling hash function", and I decided implementing it would be a
good exercise. After writing that, writing a hash table was simple.
2020-11-16 00:35:01 +00:00
William Carroll
363519273a Find the intersection (if any) between two linked lists
As with most linked list questions, this one involves an arcane trick from the
neck-bearded playbook.
2020-11-15 17:42:44 +00:00
William Carroll
c8330adfcb Solve "Move Zeroes to End"
Write a function to modify an array of integers in-place such that all of the
zeroes in the array are at the end, and the order of the other integers is not
changed.
2020-11-15 13:51:46 +00:00
William Carroll
09cd819a70 Include re-roll strategy for rand7
After seeing the solution that my book advocated, I implemented it using
recursion.
2020-11-14 17:36:04 +00:00
William Carroll
5820f6f459 Solve rand7
Write a random number generator for [0,7) using only a random number generator
for [0,5). Ensure the results are uniformly distributed.
2020-11-14 17:26:00 +00:00
William Carroll
a0e9e2b310 Solve unsorted-substring a second time
This solution operates in O(n) time instead of O(n*log(n)) time, which
surprisingly isn't *that* big of a difference...

Consider a size of n of 10M...
  1) ~10s
  2) ~0.5s

So, yes, the O(n*log(n)) will take 100x longer to complete, but for an enormous
input size of 10M elements, it can still complete in under a minute. The
difference between that and the second, faster, algorithm, is just 9s.
2020-11-14 15:28:23 +00:00
William Carroll
48fde5f278 Solve unsorted-substring
Write a function that returns the indices demarcating a substring, which if
sorted, would make the entire array sorted.
2020-11-14 15:08:25 +00:00
William Carroll
47c5c6ac05 Partially implement a Heap
Defining the insert (or "siftup") function described in the "Programming Pearls"
book.
2020-11-14 14:08:58 +00:00
William Carroll
c841527f61 Write encoded XML parser and pretty-printer
Write a function that reads a string of compressed XML and outputs the
decompressed version.

Note to self: Now that I'm growing more comfortable writing parsers, I'd like to
become equally comfortable writing pretty-printers.
2020-11-14 14:00:00 +00:00
William Carroll
bfd2180e6b Solve tic-tac-toe checker
Write a function that verifies whether or not a tic-tac-toe board is valid.
2020-11-13 17:45:07 +00:00
William Carroll
1b3f1b99f5 Solve box-stacking problem
Write a function to compute the highest stack of boxes that can be created from
a list of boxes.
2020-11-13 16:57:47 +00:00
William Carroll
7672049e1c Solve N queens
After a five year hiatus, I decided to attempt to solve the famous N queens
problem again. This time, instead of modeling the chess board using a
`[[Bool]]`, I'm using `[Integer]` where the `Integer` indicates which column has
a queen. This is a bit lighter in RAM.
2020-11-13 16:56:02 +00:00
William Carroll
14f6169fcf Document subset of BNF for regex engine
Adding some documentation for my future self.
2020-11-13 16:55:39 +00:00
William Carroll
aa66d9b83d Add coding exercises for Facebook interviews
Add attempts at solving coding problems to Briefcase.
2020-11-12 14:37:29 +00:00
William Carroll
d2d772e43e Sort Emacs deps
Group Emacs dependencies like ivy together.
2020-11-12 11:20:27 +00:00
William Carroll
6d26f5b987 Mark additional movies as watched
Making progress...
2020-11-12 11:19:59 +00:00
William Carroll
69b6bda01b Style habit screen to accommodate footer
Add spacing to the bottom to make space for the footer.
2020-11-12 11:19:30 +00:00
William Carroll
2290aac2a8 Tweak styles
Add spacing to help the app breathe.
2020-10-11 16:47:31 +01:00
William Carroll
767fed75c3 Support multiple HabitTypes
I could have and should have broken this change into smaller pieces, but when I
came up for air, I had changed too much, and most of the changes are
intermingled. Oh well... this is an exciting change!

Include habits for:
- Morning
- Evening
- Payday (the 25th)
- First of the Month
- First of the Year

Since the Morning and Evening routines might be a bit noisy, I'm excluding them
from the output using a flag, `include{Morning,Evening}`, which I support in the
UI to toggle their visibility.

I made *much* more progress on this app that I expected to today, and I *think*
-- short of supporting a database and a server -- I'm close to
being *completely* finished.

Wahoo!
2020-10-11 16:40:10 +01:00
William Carroll
abf1875934 Support Msg to clear all completed tasks
Add a simple button to clear all completed tasks.
2020-10-11 15:39:01 +01:00
William Carroll
79cf42abd5 Render time remaining in UI
Show the number of minutes remaining before completing all of the tasks.
2020-10-11 15:17:20 +01:00
William Carroll
5684608fed Move tailwind function into Utils module
Instead of accepting `List (String, Int)`, accept `List Strategy` where
`Strategy` defines whether or not the string of selectors should be applied to
the element.

I'm also renaming it `class` so I can just use `Utils.class`; `tailwind` has
little to do with the function itself.
2020-10-11 14:59:42 +01:00
William Carroll
1c8a8f5d2c Expand Habit type
Include:

- habitType: Daily, Weekly, Yearly... what's the trigger?
- minutesDuration: Estimation of how long it'll take to complete
2020-10-11 14:58:49 +01:00
William Carroll
ea0cd01e18 Watch a few movies
Here's what I watched:
- Ran
- Children of Heaven
- Lawrence of Arabia

Only 78/250 movies to go!
2020-10-11 10:28:46 +01:00
William Carroll
05d52e403c Tweak styles
- Change header to blue
- Change habit to gray when completed
- Prefer app font for footer instead of monospaced font
2020-10-11 10:24:11 +01:00
William Carroll
0a15ea7366 Create UI module for common components
Create UI.elm to house components like `button`, which is a simple HTML button
with `focus:outline-none` applied as a `class`, which is an accessibility
feature that I don't need for this touch-screen application.

I like this pattern more than my more opinionated patterns for UI modules in Elm
where I'd define all of the arguments as a record type (i.e. kwargs).
2020-10-11 10:15:03 +01:00
William Carroll
106457de4b Prefer handwritten font
Use the Google Fonts API to fetch a handwritten font, which gives the app a
modicum of personality. There are more "best practices" ways to do this, such
as:

- Download the font once, and include it in the bundle
- Extend the Tailwind configure to recognize the font
- Ditch the inline <style> block

But I don't need the performance benefits that the first bullet provides. And
the second two bullets are more relevant for a larger application with more than
one font. So I think in this case, the easiest solution is best.

Also:
- Use `container` and `mx-auto` to constrain content for wide screens
2020-10-11 10:09:15 +01:00