Day 7

Photo by Glenn Carstens-Peters on Unsplash

Given a linked list, uniformly shuffle the nodes. What if we want to prioritize space over time?

https://dailycodingproblem.com

**Given the problem’s instructions, it was assumed that the linked list was not circular, and therefore had an end element.**

When trying to figure out the solution to this problem, I first searched the internet for ways to “uniformly” shuffle an array. I came across this stackoverflow question, which led me to the Fisher—Yates shuffle. This algorithm shuffles all the elements in-place, which makes it quite space-efficient.

Next, I considered the different ways in which the linked list could be optimized in order to take the least time. My first thought was that it would make the whole process quicker if I could get it out of the form of a linked list and into an object format to make fetching each node much faster. The algorithm might look something like this:

1. Turn the linked list into an object data structure (n operations)

2. Shuffle the linked list (n operations)

3. Turn the object back into a linked list (n operations)

The number of operations required would total to: 3n

The alternative option would be to go through the linked list each time. It might look something like this:

- Picking a random number from the list (n operations to figure out how long the linked list is)
- Taking a random element from the list and moving it to the end ([n(n+1)]/2 operations)

The number of operations required would total to: [n^2+3n]/2

To find out which option would be more efficient at different linked list lengths, I plugged the equations into desmos:

And found that when the list contained less than 3 nodes, option 2 was more efficient, but as soon as the number of nodes passed 3, the first option was more efficient. That being said, option 1 is much less space efficient.

**In solving the problem, I plan on writing both algorithms so as to provide code samples of each one.**

First, I wrote the code that would be shared between both options. This includes the “Link” class (since `Node`

is reserved in TypeScript), a helper function `constructList`

that constructs a linked list of a given length, and another helper function `printList`

that prints the list values using arrows (for debug purposes).

```
class Link {
val?: any
next?: Link = null
constructor(val: any) {
this.val = val
}
setNext (node: Link) {
this.next = node
return this
}
}
function constructList (length: number) {
if (length < 1) {
throw new Error('Length cannot be less than 1')
} else if (length === 1 ) {
return new Link(1)
} else {
return new Link(length).setNext(constructList(length - 1))
}
}
function printList (list: Link, message = '') {
if (list.next === null) {
console.log(`${message}${list.val}`)
} else {
message += `${list.val} -> `
printList(list.next, message)
}
}
```

```
const list = constructList(100)
function listToArray (list: Link): Link[] {
if (list.next === null) {
return [list]
} else {
const currentLink = list
const nextLink = currentLink.next
currentLink.next = null
return [currentLink].concat(listToArray(nextLink))
}
}
function randomizeTimeEfficient (list: Link) {
const arrayFormat = listToArray(list)
return randomizeTimeEfficientRecursive(arrayFormat)
}
function randomizeTimeEfficientRecursive (list: Link[], current?: Link) {
const length = list.length
if (length === 0) {
return current
}
const randomIndex = Math.round(Math.random() * length)
const randomLink = list[randomIndex]
// Construct a list without the randomIndex
const nextList = list.slice(0, randomIndex).concat(list.slice(randomIndex + 1))
if (current) {
current.setNext(randomizeTimeEfficientRecursive(nextList, randomLink))
return current
} else {
return randomizeTimeEfficientRecursive(nextList, randomLink)
}
}
```

**Unfortunately, I did not have time today to complete this algorithm. Instead of working on my next daily coding problem, I will try and complete this one and then update this post accordingly.**

Day 6

Photo by Dominik Scythe on Unsplash

Write an algorithm that finds the total number of set bits in all integers between

https://dailycodingproblem.com`1`

and`N`

Today I decided that I would switch up my coding problem language and give python a try. Unfortunately, the syntax highlighter that is used does not have python as an option, but feel free to view the code using the button below.

```
# Helper method to convert a number to binary
def convertToBinary(num):
return str(bin(num))[2:]
# The main method
def bits(n):
if n == 0:
return 0
else:
binary = convertToBinary(n)
count = binary.count('1')
return count + bits(n - 1)
# Should return 4
print(bits(3))
# Should return 2222
print(bits(500))
```

]]>

Day 5

Photo by Jeremy Thomas on Unsplash

You have

`N`

stones in a row, and would like to create from them a pyramid. This pyramid should be constructed such that the height of each stone increases by one until reaching the tallest stone, after which the heights decrease by one. In addition, the start and end stones of the pyramid should each be one stone high.You can change the height of any stone by paying a cost of

`1`

unit to lower its height by`1`

, as many times as necessary. Given this information, determine the lowest cost method to produce this pyramid.For example, given the stones

https://dailycodingproblem.com`[1, 1, 3, 3, 2, 1]`

, the optimal solution is to pay`2`

to create`[0, 1, 2, 3, 2, 1]`

.

```
const stones = [1, 1, 3, 3, 2, 1]
const otherStones = [3, 3, 3, 3, 3]
const removeAtIndex = (arr, index) => arr.slice(0, index).concat(arr.slice(index + 1))
const optimalCost = (stones) => {
return recursiveCost(stones)
}
const recursiveCost = (stones, cost = 0, pyramid = [], total = 0) => {
// Define the expected total length of and the current index
const length = stones.length + pyramid.length
const index = length - stones.length
// Define what the next element should look like
let want
if (index < length / 2) {
want = index + 1
} else {
want = length - index - ((length + 1) % 2)
}
// End recursion if the want is less than or equal to 0
if (want <= 0 && pyramid.length === length) return total
const lookingFor = want + cost
const foundIndex = stones.indexOf(lookingFor)
// If the element exists
if (foundIndex >= 0) {
const nextStones = removeAtIndex(stones, foundIndex)
const nextPyramid = pyramid.concat([want])
const nextTotal = total + cost
return recursiveCost(nextStones, 0, nextPyramid, nextTotal)
} else {
// Otherwise increase cost and try again
return recursiveCost(stones, cost + 1, pyramid, total)
}
}
```

]]>Day 4

Photo by Viktor Forgacs on Unsplash

An imminent hurricane threatens the coastal town of Codeville. If at most two people can fit in a rescue boat, and the maximum weight limit for a given boat is k, determine how many boats will be needed to save everyone.

For example, given a population with weights [100, 200, 150, 80] and a boat limit of 200, the smallest number of boats required will be three.

https://dailycodingproblem.com

```
const weights = [100, 200, 150, 80]
const otherWeights = [30, 70, 40, 200, 100, 150, 80]
const limit = 200
const numberOfBoats = (w, k) => {
return recursiveBoats(w, k)
}
const recursiveBoats = (w, k, i = 1, max = 1, boats = 0) => {
const element = w[0]
if (w.length === 0) {
return boats
} else if (i >= w.length || element + w[max] === k) {
// Remove the element that was the maximum under the limit if it exists
let newWeights
if (element + w[max] <= k) {
newWeights = w.slice(1, max).concat(w.slice(max + 1))
} else {
newWeights = w.slice(1)
}
return recursiveBoats(newWeights, k, 1, 1, boats + 1)
}
const comparison = w[i]
if (element + comparison < k && (element + w[max] > k || comparison > w[max])) {
return recursiveBoats(w, k, i + 1, i, boats)
}
return recursiveBoats(w, k, i + 1, max, boats)
}
const result1 = numberOfBoats(weights, limit)
console.log('Number of boats for first weights:')
console.log(result1)
const result2 = numberOfBoats(otherWeights, limit)
console.log('Number of boats for second weights:')
console.log(result2)
```

]]>

Day 3

Photo by Mateusz Delegacz on Unsplash

A wall consists of several rows of bricks of various integer lengths and uniform height. Your goal is to find a vertical line going from the top to the bottom of the wall that cuts through the fewest number of bricks. If the line goes through the edge between two bricks, this does not count as a cut.

For example, suppose the input is as follows, where values in each row represent the lengths of bricks in that row

```
[[3, 5, 1, 1],
[2, 3, 3, 2],
[5, 5],
[4, 4, 2],
[1, 3, 3, 3],
[1, 1, 6, 1, 1]]
```

The best we can we do here is to draw a line after the eighth brick, which will only require cutting through the bricks in the third and fifth row.

https://dailycodingproblem.com

Given an input consisting of brick lengths for each row such as the one above, return the fewest number of bricks that must be cut to create a vertical line.

```
const wall = [
[3, 5, 1, 1],
[2, 3, 3, 2],
[5, 5],
[4, 4, 2],
[1, 3, 3, 3],
[1, 1, 6, 1, 1]
]
const leastCuts = (wall) => {
let rowSum = 0
const data = {}
for (let row of wall) {
rowSum = 0
for (let col of row.slice(0, row.length - 1)) {
rowSum += col
if (data[rowSum] === undefined) data[rowSum] = 0
data[rowSum] += 1
}
}
const mostCommonCut = Object.keys(data)
.map(str => +str)
.sort((a, b) => data[b] - data[a])[0]
return wall.length - +data[mostCommonCut]
}
```

In solving this problem, I quickly realized that it was not as complex as it seemed. The question was really asking, find the most common slit out of all the rows. For example, when taking the first row of the wall:

`[3, 5, 1, 1]`

There is a slit at 3, 8, 9, and, of course, 10.

The code that I wrote simply computed and stored the number of slit totals throughout the entire wall, sorted those by largest to smallest in number, and then subtracted the number (4 in the case of the sample wall given) from the height of the wall—6 rows.

Even though this was one of the more easy problems, there are many optimizations that can make it much faster. For example, the for loop can be broken out of much sooner if it can be determined that in the remaining rows, none of the slits in second place are able to catch up.

In order to achieve that level of optimization however, it is most likely that a more complex data structure be used than just an object for keeping data on the most common cuts through the wall. Not only would each item need to keep its wall position and count, but it would also need to keep its relation to other items’ count.

In my solution, the browser’s sorting algorithm was used, but the browser’s sorting algorithm assumes nothing about the data, whereas in this problem it is most likely the case that most of the data is similar in length, so a different sorting algorithm than the browser’s default might make finding the most common slit position much faster.

One last thing that could be optimized is the algorithm itself. For example, if paired with the few repetitions optimization, it would be much faster to start with the rows that have fewer elements. See the following order of visiting the rows:

```
[[3, 5, 1, 1],
[2, 3, 3, 2],
[5, 5],
[4, 4, 2],
[1, 3, 3, 3],
[1, 1, 6, 1, 1]]
```

- Row 3
- Row 4
- Row 1, 2, 5

In this particular map, going in that order does not help improve algorithm speed, but it would most likely increase algorithm speed on much bigger maps where slit overlap is less common and there is a cut that is more common than all other cuts.

]]>Day 2

Photo by Chris Barbalis on Unsplash

Two nodes in a binary tree can be called cousins if they are on the same level of the tree but have different parents. For example, in the following diagram

`4`

and`6`

are cousins.

```
1
/ \
2 3
/ \ \
4 5 6
```

Given a binary tree and a particular node, find all cousins of that node.

https://dailycodingproblem.com

First, I created a Node class in order to construct the binary tree

```
class Node {
constructor (value) {
this.right = null
this.left = null
this.value = value
}
setRight (rightNode) {
this.right = rightNode
return this
}
setLeft (leftNode) {
this.left = leftNode
return this
}
}
```

Next, I defined the tree

```
const tree = new Node(1)
.setLeft(new Node(2)
.setLeft(new Node(4)))
.setRight(new Node(5))
.setRight(new Node(3)
.setRight(new Node(6)))
```

To me, the most applicable search for this problem seemed to be a breadth-first search.

Breadth-first search, Wikipedia

Breadth-first search(BFS) is an algorithm [that] explores all of the neighbor nodes at the present depth prior to moving on to the nodes at the next depth level.

With breadth-first search, it is much easier to get nodes at the same level, since the tree is traversed row after row instead of going down an entire branch and then continuing onto the next branch.

With this in mind, I came up with my first attempt at an algorithm:

```
const findCousins = (tree, number) => {
return recursiveFindCousins([tree], number, 1, 1, [])
}
const recursiveFindCousins = (queue, number, depth, remaining, visited) => {
const node = queue[0]
if (remaining === 0) {
// Increase the depth, clear the visited list, and reset the remaining nodes
return recursiveFindCousins(queue, number, depth + 1, queue.length, [])
} else if (node.value === number) {
// Only return if the depth is greater than 2, otherwise throw an error
if (depth > 2) {
return visited.concat(queue.slice(0, remaining)) // return the cousins
}
return new Error('The number cannot be in the first two rows')
} else {
// --- Prepare for next recursive call ---
queue = queue.concat([node.left, node.right].filter(notNull => notNull))
visited.push(node)
// --- Recursive call ---
return recursiveFindCousins(queue.slice(1), number, depth, remaining - 1, visited)
}
}
```

The `findCousins`

function takes in a tree and a number to look for throughout the tree. It then calls a `recursiveFindCousins`

function with the necessary arguments of a `queue`

, `number`

, `depth`

, `remaining`

, and `visited`

.

The `queue`

argument is the number of remaining nodes in the current queue; this is how the breadth-first logic comes in.

The `number`

argument is the number to look for throughout the tree. This value stays constant throughout all of the recursive calls.

The `depth`

argument is the current depth in the tree. This value is important because if the depth is less than 2, the function should return an error. How can a node have a cousin if there is only a parent with children?

The `remaining`

argument is the number of remaining nodes at the current depth. When remaining reaches 0, the number of remaining nodes is set to the length of the queue, the visited list of nodes (as described below) is cleared, and the depth is incremented.

The `visited`

argument is a list of the nodes that are visited. This list is cleared as soon as the number of remaining nodes hits 0.

In order for the problem to be completed, the values returned could not return the current node nor sibling nodes, only cousin nodes.

To fix this, the array was trimmed accordingly.

See the final code below:

```
const recursiveFindCousins = (queue, number, depth, remaining, visited) => {
const node = queue[0]
if (remaining === 0) {
// Increase the depth, clear the visited list, and reset the remaining nodes
return recursiveFindCousins(queue, number, depth + 1, queue.length, [])
} else if (node.value === number) {
// Only return if the depth is greater than 2, otherwise throw an error
if (depth > 2) {
// Only return every other branch except for the current parent's children
const cousins = visited.concat(queue.slice(0, remaining))
const position = cousins.length - remaining
const pair = Math.floor(position / 2)
const beforePair = cousins.slice(0, 2 * pair)
const afterPair = cousins.slice(2 * (pair + 1))
return beforePair.concat(afterPair)
}
return new Error('The number cannot be in the first two rows')
} else {
// --- Prepare for next recursive call ---
queue = queue.concat([node.left, node.right].filter(notNull => notNull))
visited.push(node)
// --- Recursive call ---
return recursiveFindCousins(queue.slice(1), number, depth, remaining - 1, visited)
}
}
```

]]>Day 1

You are given an array representing the heights of neighboring buildings on a city street, from east to west. The city assessor would like you to write an algorithm that returns how many of these buildings have a view of the setting sun, in order to properly value the street.

For example, given the array

https://dailycodingproblem.com`[3, 7, 8, 3, 6, 1]`

, you should return`3`

, since the top floors of the buildings with heights`8`

,`6`

, and`1`

all have an unobstructed view to the west.

```
const map = [3, 7, 8, 3, 6, 1]
const haveAView = (input) => input.reduce((acc, building, i) => {
const nextBuilding = input[i + 1]
const isCovered = nextBuilding && (nextBuilding > building)
return acc + (isCovered ? 1 : 0)
}, 0)
const result = haveAView(map)
console.log(result)
```

This solution turned out to be incorrect. If one were to take the sample building map of:

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

It is clear that running the function above would result in an output of 4, even though it should in fact be three. The previous function **only considered the next building** when determining if a particular building was covered, and not the subsequent ones.

I updated my solution by including a recursive element in which if the input size does not match the output size, then the function is called again recursively with the output building set instead. This means that if they are in order: great, it returns the length. If they are not in order, the function is run again, eliminating at least one more building that is in the incorrect order. This process repeats until all of the buildings have been tested and none of them are being blocked by another building.

```
const map = [3, 7, 8, 3, 6, 1] // 3
const map2 = [3, 7, 9, 5, 4, 8, 2, 1, 3] // 3
const haveAView = (input) => {
// Filter the "buildings" based on the height of the next one
const output = input.reduce((acc, building, i) => {
const nextBuilding = input[i + 1]
const isCovered = nextBuilding && (nextBuilding > building)
if (!isCovered) {
return acc.concat([building])
}
return acc
}, [])
// If the output length is the same as the input length, return
if (output.length === input.length) {
return output.length
}
// Otherwise run the function again until the lengths are equal
return haveAView(output)
}
const result = haveAView(map)
console.log('[Map 1] Should output 3')
console.log(result)
const result2 = haveAView(map2)
console.log('[Map 2] Should output 3')
console.log(result2)
```

]]>