Cassidoo Interview question of the week

My answers to the inteview questions from Cassidoo newsletter.

January 2024

You can find here my submissions to the Interview questions of the week from Cassidoo newsletter !

15-04-2024

Given a string str, write a function to determine the longest substring containing only two unique characters.

Result: 5
    const longestSubstrofTwoUniqueChars = (str) => {
        if (str.length < 3) {
            return str.length
        }
        
        let charsByCount = {}
        let start = 0
        let maxCount = 0;

        charsByCount[str[start]] = (charsByCount[str[start]] || 0) + 1;

        for (let end = 1; end < str.length; end++) {
            charsByCount[str[end]] = (charsByCount[str[end]] || 0) + 1;

            while (true) {
                if (Object.values(charsByCount).length > 2) {
                    charsByCount[str[start]] = charsByCount[str[start]] - 1
                    if (charsByCount[str[start]] === 0) {
                        delete charsByCount[str[start]]
                    }
                    start++
                    continue
                }
                break
            }

            if (end - start + 1 > maxCount) {
                maxCount = end - start + 1
            }
        }

        return maxCount
    }

08-04-2024

Imagine you have n dice, and each die has m faces on it (so the numbers are from 1 to m). Write a function where, given an integer target, it returns the number of possible ways to roll the dice to get the sum of target face up.

Dice Sum115
    const diceSum = (dies, faces, target) => {
        if (target < dies || target > dies * faces) {
            return 0;
        }
    
        const dp = Array.from({ length: dies + 1 }, () => Array(target + 1).fill(0));
    
        for (let i = 1; i <= faces && i <= target; i++) {
            dp[1][i] = 1;
        }

        for (let dice = 2; dice <= dies; dice++) {
            for (let dice_value = 1; dice_value <= target;dice_value++) {
                for (let i = 1; i <= faces && i < dice_value; i++) {
                    dp[dice][dice_value] += dp[dice - 1][dice_value - i];
                }
            }
        }
    
        return dp[dies][target];
    }

01-04-2024

Given an array of numbers, add all of the values together but only if the number doesn’t repeat a digit.

11
x
12
x
22
x
23
x
Sum of valid numbers is: 35
    function sumUniqueNumbers(arr) {
        let sum = 0;
        for (let num of arr) {
            if (isUnique(num)) {
                sum += num;
            }
        }
        return sum;
    }
    
    function isUnique(num) {
        const numString = num.toString();
        const digitSet = new Set();
        for (let digit of numString) {
            if (digitSet.has(digit)) {
                return false;
            }
            digitSet.add(digit);
        }
        return true;
    }

25-03-2024

Given a 2D array of 0s and 1s, where 0 represents water and 1 represents land, return the size of the largest “island” in the water. Diagonal connections don’t count!

0
1
1
1
0
0
0
1
1
0
1
1
1
0
1
0
0
0
0
1
0
0
0
0
0
1
0
0
0
1
1
0
1
1
1
0
Click on the cells to switch them from sea to land or from land to sea!
Biggest island size = 7
    const maxAreaOfIsland = (originalMap) => {
        let islandMap = originalMap.map(r => r.map(c => c))
        let biggest = 0
        
        for (let i = 0; i < islandMap.length; i++) {
            for (let j = 0; j < islandMap[i].length; j++) {
            if (islandMap[i][j] === 1) {
                biggest = Math.max(biggest, dfs(islandMap, i, j))
            }
            }
        }
        return biggest
        }
    
    const dfs = (islandMap, x, y) => {
        if (x < 0 || x >= islandMap.length || y < 0 || y >= islandMap[0].length || islandMap[x][y] === 0) {
            return 0
        }        
        islandMap[x][y] = 0
        
        return 1 + dfs(islandMap, x + 1, y) + dfs(islandMap, x - 1, y) + dfs(islandMap, x, y + 1) + dfs(islandMap, x, y - 1)
    }

18-03-2024

Given an integer array, write a function hills(arr) and a function valleys(arr) that return the number of hills and valleys, respectively, in the array.

Hills: 0

Valleys: 0

    const hills = (arr) => elevation(arr, false)
    const valleys = (arr) => elevation(arr, true)

    const elevation = (arr, down) => {
        let c = 0
        
        let mark = false
        for (let i = 1;i<arr.length;i++) {
            if ((down && arr[i] < arr[i-1]) || (!down && arr[i] > arr[i-1]) ) {
                mark = true
            }

            if (mark && ((down && arr[i] > arr[i-1]) || (!down && arr[i] < arr[i-1]))) {
                c++
                mark = false
            }
        }
        return c
    }

11-03-2024

Given an integer array arr, return the maximum difference between two successive elements in arr’s sorted form. Return 0 if there’s 0 or 1 elements.

Max difference for is 0

    const maxDiff = (arr) => {
        arr.sort((a, b) => a > b)

        let max = 0
        for (let i = 1;i<arr.length;i++) {
            const diff = arr[i] - arr[i-1]
            if (diff > max) {
                max = diff
            }
        }

        return max
    }

04-03-2024

Make a pomodoro timer where a user can start the timer, pause for a set break time, and continue after the break.

Wanted to do some react, not the prettiest code but it works !

Without any Css, here’s the component, the times used for the demo are 5 seconds of work, and 3 seconds of break. It will alternate automatically between the two and you can pause the timer completely if needs be.


import { useState, useEffect } from 'react';

const Timer = () => {
  const [state, setState] = useState("")
  const [resumeTo, setResumeTo] = useState("")
  
  const [timeLeft, setTimeLeft] = useState(null)

  const work = () => {
    setState("work")
    setTimeLeft(15 * 1000)
  }

  const breakTime = () => {
    setState("break")
    setTimeLeft(5 * 1000)
  }

  const pause = () => {
    setResumeTo(state)
    setState("pause")
  }

  useEffect(() => {
    const intervalId = setInterval(() => {
      if (state !== "pause" && state !== "") {
        setTimeLeft((_timespan) => _timespan - 1_000);
      }
    }, 1_000);
      
    return () => {
      clearInterval(intervalId);
    };
  });

  if (state === "work" && timeLeft / 1000 === 0) {
    setState("break")
    setTimeLeft(3 * 1000)
    breakTime()
  }
  if (state === "break" && timeLeft / 1000 === 0) {
    work()
  }

  const formatTimer = (timeToFormat) => {
    const mins = Math.floor(timeToFormat / 60 / 1000)
    const secs = (timeToFormat / 1000) - Math.floor(timeToFormat / 60 / 1000)*60

    return <span>{String(mins).padStart(2, '0')}:{String(secs).padStart(2, '0')}</span>
  }

  if (state === "") {
    return <button onClick={work} >Start pomodoro</button>
  }

  return (
    <div className="timer">
      { state !== "pause" && <button onClick={pause}>Pause</button>}
    
      {
        state === "pause"
        ? <>
          <button onClick={() => setState(resumeTo)}>Resume the {resumeTo}</button>
          <div>Time left in {resumeTo} => {formatTimer(timeLeft)} </div>
        </>
        : <div>{state === "work" ? "Break" : "Work"} in {formatTimer(timeLeft)} </div>
      }
    </div>
  );
};

export default function App() {
  return <Timer />
}

26-02-2023

Given a number and a digit to remove from that number, maximize the resulting number after the digit has been removed and print it.

function removeDigit(number, needle) {
    haystack = number.toString()
    let biggestNumber = 0;
    for(let i = 0; i < haystack.length; i++) {
        if (haystack[i] === needle.toString()) {
            const cleaned = haystack.slice(0, i) + haystack.slice(i+1)
            if (parseInt(cleaned) > biggestNumber) {
                biggestNumber = parseInt(cleaned)
            }
        }
    }
    return biggestNumber === 0 ? number : biggestNumber
}

console.log(removeDigit(31415926, 1)) // 3415926
console.log(removeDigit(1231, 1)) // 231

19-02-2023

Given a string array, find the maximum product of word lengths where the words don’t share any letters.

(Given the example and how late I was to send this, I assumed we were looking only for the bigger product between two words)


// Example:
// > wordLengthProduct(["fish","fear","boo","egg","cake","abcdef"])
// > 16 // "fish" and "cake"

// > wordLengthProduct(["a","aa","aaa","aaaa"])
// > 0 // all of them share "a"

function wordLengthProduct(words) {
    let product = 0
    words.forEach((wordA) => {
        words.forEach((wordB) => {
            if (wordA === wordB) {
                return
            }

            if (!shareSomeLetter(wordA, wordB)) {
                const potentialProduct = wordA.length * wordB.length
                if (potentialProduct > product) {
                    product = potentialProduct
                }
            }
        })
    })

    return product
}

function shareSomeLetter(a, b) {
    if (b.length > a.length) {
        return shareSomeLetter(b, a)
    }

    for (let i = 0; i < a.length; i++) {
        if (b.includes(a[i])) {
            return true
        }
    }

    return false
}

console.log(wordLengthProduct(["fish","fear","boo","egg","cake","abcdef"])) // 16
console.log(wordLengthProduct(["a","aa","aaa","aaaa"])) // 0

12-02-2023

Write a function that produces a generator that produces values in a range.

package main

import "fmt"
import "errors"

func main() {
	generator := fromTo(0, 3)
	
	fmt.Println(generator()) // 0 <nil>
	fmt.Println(generator()) // 1 <nil>
	fmt.Println(generator()) // 2 <nil>
	fmt.Println(generator()) // -1 Generator expired
}

func fromTo(from int, to int) func() (int, error)  {
	current := from
    return func() (int, error) {
        if current < to {
            current++
            return current - 1, nil
        }
        return -1, errors.New("Generator expired")
    }
}

29-01-2024

Write a function called daysBetween that takes in two dates, and returns the number of days between those dates

function daysBetween(d1, d2) {
    d1ms = new Date(d1).getTime()
    d2ms = new Date(d2).getTime()
    
    return Math.abs(Math.round((d1ms-d2ms)/(1000*60*60*24))); 
}

console.log(daysBetween('Jan 1, 2024', 'Jan 29, 2024')) // 28
console.log(daysBetween('Feb 29, 2020', 'Oct 31, 2023')) // 1340

22-01-2024

Write a data structure for a simple binary tree, and a function that prints a given tree.

This one took a bit more time, it works, but is not as simple as I’d have hoped.

package main

import "fmt"
import "math"
import "strings"

type Node struct {
	Name string
	Left *Node
	Right *Node
}

func main() {
	root := Node{Name: "1"}
	root.Left = &Node{Name: "2"}
	root.Right = &Node{Name: "3"}
	root.Left.Left = &Node{Name: "4"}
	root.Left.Right = &Node{Name: "5"}
	root.Left.Right.Left = &Node{Name: "6"}
	root.Left.Right.Right = &Node{Name: "7"}

	printTree(root)
}

/* Output:
            1
      /            \
      2            3
   /      \
   4      5
         /  \
         6  7
*/

func getSize(root Node) int {
	if root.Left == nil && root.Right == nil { 
		return 1;
	}
	
	if root.Left == nil {
		return 1 + getSize(*root.Right)
	}

	if root.Right == nil {
		return 1 + getSize(*root.Left)
	}

	return 1 + int(math.Max(float64(getSize(*root.Left)), float64(getSize(*root.Right))))
}

func printTree(root Node) {
	size := getSize(root)

	explo := []*Node{&root}
	for i := 1; i <= size; i++{
		links := ""
		nodeNames := ""
		next := make([]*Node, 0)
		for k, node := range explo {
			nodeSize := int(math.Pow(2, float64(size - i)) * 3)
			if node == nil {
				nodeNames += strings.Repeat(" ", int(math.Floor(float64(nodeSize))) + 1)
				links += strings.Repeat(" ", int(math.Floor(float64(nodeSize))) + 1)
				next = append(next, nil, nil)
				continue
			}

			nodeNames += strings.Repeat(" ", int(math.Floor(float64(nodeSize / 2))))
			links += strings.Repeat(" ", int(math.Floor(float64(nodeSize / 2))))

			if k % 2 == 0 {
				links += "/"
			} else {
				links += "\\"
			}
			nodeNames += node.Name

			nodeNames += strings.Repeat(" ", int(math.Ceil(float64(nodeSize / 2))))
			links += strings.Repeat(" ", int(math.Ceil(float64(nodeSize / 2))))

			next = append(next, node.Left, node.Right)
		}
		if i != 1 {
			fmt.Println(links)
		}
		fmt.Println(nodeNames)
		explo = next
	}
}

15-01-2024

Given a 2D array, write a function that flips it vertically or horizontally.

First time seeing these questions, wrote this simple working solution !

const array = [
    [1,2,3],
    [4,5,6],
    [7,8,9]
]

function flip (flipper, direction) {
    if (direction === 'vertical') {
        return flipper.toReversed()
    }
    
    return flipper.map(row => row.toReversed())
}

console.log(flip(array, 'horizontal'))
//[[3,2,1],[6,5,4],[9,8,7]]

console.log(flip(array, 'vertical'))
//[[7,8,9],[4,5,6],[1,2,3]]
```../components/CassidoosInterviewQuestions/DuplicateNumbers.jsx