Giter VIP home page Giter VIP logo

eloquent-javascript-exercises's Introduction

Eloquent Javascript

Program Structure

Looping a Triangle

Problem statement

Write a loop that makes seven calls to console.log to output the following triangle:

#
##
###
####
#####
######
#######

Iterative solution

First solution

for (let x = '#'; x.length < 8; x += '#') {
    console.log(x)
}
DownsideSolution
string.length can be a slow operationuse numeric iterator
let str = '#'
for (let i = 0; i < 8; i++) {
    console.log(str)
    str += '#'
}

Recursive solution

Advantages:

  • no state
  • no side effects

Recursive solutions will have

  1. a base-case
  2. unit of work
  3. recursive call with changed value
function triangle(len) {
    // 1. define base case
    if (len > 7) { return }

    // 2. do work
    console.log('#'.repeat(len))

    // 3. recurse
    triangle(len + 1)
}

triangle(1)
DownsideSolution
can only generate triangles (or frustrums) of length 8remove hard-coded limit inside the function, pass a parameter with this information instead
// Print a triangle of arbitrary length
function triangle(len, layer = 1) {

    console.log('#'.repeat(layer))
    if (layer > len) { return }
    triangle(len, layer + 1)
}

triangle(5)

FizzBuzz

Problem Statement

Write a program that uses console.log to print all the numbers from 1 to 100, with two exceptions. For numbers divisible by 3, print “Fizz” instead of the number, and for numbers divisible by 5 (and not 3), print “Buzz” instead. When you have that working, modify your program to print “FizzBuzz” for numbers that are divisible by both 3 and 5 (and still print “Fizz” or “Buzz” for numbers divisible by only one of those).

(This is actually an interview question that has been claimed to weed out a significant percentage of programmer candidates. So if you solved it, your labor market value just went up.):

Iterative solution

let num = 1
for (let i = 0; i<100; i++) {
    if (num % 5 == 0 && num % 3 == 0) {
        console.log('FizzBuzz')
    }
    else if(num % 5 == 0 && num % 3 !== 0) {
        console.log('Buzz')
    }
    else if(num % 3 == 0) {
        console.log('Fizz')
    }
    else { (console.log(num))
    }
    num += 1
}

Functional solution

const _ = require('lodash')

_.each(_.range(1, 101), fizzbuzz)

function fizzbuzz(num) {
    if (num % 5 == 0 && num % 3 == 0) {
        console.log('FizzBuzz')
    }
    else if(num % 5 == 0 && num % 3 !== 0) {
        console.log('Buzz')
    }
    else if(num % 3 == 0) {
        console.log('Fizz')
    }
    else {
        console.log(num)
    }
}

Chessboard

Problem statement

Write a program that creates a string that represents an 8×8 grid, using newline characters to separate lines. At each position of the grid there is either a space or a “#” character. The characters should form a chessboard. Passing this string to console.log should show something like this:

# # # #
 # # # #
# # # #
 # # # #
# # # #
 # # # #
# # # #
 # # # #

When you have a program that generates this pattern, define a binding size = 8 and change the program so that it works for any size , outputting a grid of the given width and height.

Iterative solution

First solution

const size = 3

// let common = '# '.repeat(size/2.0 + 1)

// for (let i = 0; i < size; ++i) {
//     let output = (i % 2  ? " " : "") + common
//     console.log(output.substring(0, size))
// }

for (let row = 0; row < size; ++row) {
    let output = ''
    for (let col = 0; col < (row % 2 ? size - 1 : size); ++col) {
        output += col % 2 ? " " : "#"
    }
    console.log((row % 2 ? " " : "") + output)
}

Functional solution

Second solution

const _ = require('lodash')

const size = 8

_.each(_.range(0, size), print_row)

function print_row(i) {
    const output = (i % 2 ? " " : "") + '# '.repeat(size/2.0 + 1)
    console.log(output.substring(0, size))
}

Functions

Minimum

Problem statement

The previous chapter introduced the standard function Math.min that returns its smallest argument. We can build something like that now. Write a function min that takes two arguments and returns their minimum.

Functional solution

function min(num1, num2) {
    return num1 < num2 ? num1 : num2
}

console.log(min(4,8))
console.log(min(6,12))
console.log(min(10,10))
console.log(min(7,-5))
console.log(min(1,0))
console.log(min(-1,0))

Recursion

Problem Statement

We’ve seen that % (the remainder operator) can be used to test whether a number is even or odd by using % 2 to see whether it’s divisible by two. Here’s another way to define whether a positive whole number is even or odd: • Zero is even. • One is odd. • For any other number N, its evenness is the same as N - 2. Define a recursive function isEven corresponding to this description. The function should accept a single parameter (a positive, whole number) and return a Boolean. Test it on 50 and 75. See how it behaves on -1. Why? Can you think of a way to fix this?

Functional Solution

function isEven(N) {
    if (N == 0) {
        return true
    } else if (N == 1) {
        return false
    } else {
        return isEven(Math.abs(N-2))
    }
}
console.log(isEven(50))
console.log(isEven(75))
console.log(isEven(-1))

Bean Counting

Problem Statement

You can get the Nth character, or letter, from a string by writing “string”[N] . The returned value will be a string containing only one character (for example, “b” ). The first character has position 0, which causes the last one to be found at position string.length - 1 . In other words, a two-character string has length 2, and its characters have positions 0 and 1. Write a function countBs that takes a string as its only argument and returns a number that indicates how many uppercase “B” characters there are in the string. Next, write a function called countChar that behaves like countBs , except it takes a second argument that indicates the character that is to be counted (rather than counting only uppercase “B” characters). Rewrite countBs to make use of this new function.

Functional Solution

const _ = require('lodash')

function countBs(string) {
    // let res = 0
    // _.each(string, (letter) => {
    //     if (letter == "B") {
    //         res += 1
    //     }
    // })
    // return res
    return countChar(string, "B")
}

// for (let character of "fluffypony") {
//     console.log('character is', character)
// }

console.log(countBs("BaBoon"))

// function countBs(string) {
//     let res = 0
//     let N = 0
//     while (N < string.length) {
//         if (string[N] == "B") {
//             res += 1
//         }
//         N += 1
//     }
//     return res
// }

function countChar(string, match) {
    let res = 0
    _.each(string, (letter) => {
        if (letter == match) {
            res += 1
        }
    })
    return res
}

Solving a Maze

The goal is to create a maze solver, where the input is of the following format

S#####
.....#
#.####
#.####
...#.G
##...#
##############################################
S..#.................#.....#.....#........#..#
#..#..#############..#..#..#..#..#..####..#..#
#..#..#...........#.....#.....#..#.....#..#..#
#..#..#..######################..####..#..#..#
#.....#.....#.....#..............#.....#..#..#
##########..#..#..####..################..#..#
#...........#..#........#.....#...........#..#
#..#######..#..##########..#..#..####..####..#
#........#.................#..#.....#........#
####..##########..##########..####..##########
#.....#...........#...........#.....#........#
#..####..##########..##########..##########..#
#..#..#..#........#........#.....#........#..#
#..#..#..#..####..#######..####..#..#..####..#
#..#..#..#..#.....#.....#...........#........#
#..#..#..#..##########..######################
#.....#..#...........#..#..............#.....#
#######..##########..#..####..#######..#..#..#
#........#...........#.....#........#..#..#..#
#..#######..#..##########..#######..#..#..####
#........#..#..#........#..#.....#..#........#
####..#..#..#..#..#..####..#..#..#..#######..#
#..#..#.....#..#..#..#.....#..#..#.....#..#..#
#..#..##########..#..#..####..#..####..#..#..#
#.....#.....#.....#..#........#.....#..#..#..#
#..####..#..#..####..#..#######..#..#..#..#..#
#.....#..#.....#.....#.....#.....#..#..#..#..#
####..####..####..#######..#..####..#..#..#..#
#..............#...........#.....#.....#.....G
##############################################
##############################################
G.##.................#.....#....###......##..#
#.##.###############.#.##.##.##.##..####.###.#
#.##.##...........#....##....##.###....#.###.#
#.##.##.#######################.#####.##.###.#
#.....#.....##....#.............S#.....#.###.#
##############################################

And

SymbolDenotes
’.’where the robot can move (open positions)
’#’obstacles (blocked positions)
‘S’start position (here, x=0, y=0)
‘G’goal (here, x=5, y=4)

Recursive solution

const fs = require('fs')
const _ = require('lodash')


function readMaze(file) {
    let fileContents = fs.readFileSync(file).toString('utf-8').trim()
    let lines = fileContents.split('\n')
    let maze = _.map(lines, (line) => line.split(''))
    return maze
}

function findStart(maze) {
    for(row = 0; row < maze.length; ++row) {
        for(col = 0; col < maze[row].length; ++col) {
            if (maze[row][col] === 'S') {
                return [row, col]
            }
        }
    }
}

function printMaze(maze) {
    console.log('----------------------------')
    _.each(maze, (array) => {
        console.log(array.join(''))

    })
}
function isSearchable(maze, row, col) {
    return (maze[row][col] === '.' || maze[row][col] === 'G') &&
        (row >= 0 && row < maze.length &&
         col >= 0 && col < maze[row].length)
}

function solve(maze, row, col) {
    let finalMaze = undefined

    function depthFirstSearch(maze, row, col) {

        if (finalMaze) {
            return
        }
        printMaze(maze)

        if (maze[row][col] === 'G') {
            finalMaze = maze
            return
        }
        else if (maze[row][col] !== 'S') {
            maze[row][col] = 'W'
        }
        if (isSearchable(maze, row + 1, col)) {
            depthFirstSearch(maze, row + 1, col)
        }
        if (isSearchable(maze, row - 1, col)) {
            depthFirstSearch(maze, row - 1, col)
        }
        if (isSearchable(maze, row, col + 1)) {
            depthFirstSearch(maze, row, col + 1)
        }
        if (isSearchable(maze, row, col - 1)) {
            depthFirstSearch(maze, row, col - 1)
        }
        if (finalMaze === undefined) {
            maze[row][col] = 'V'
        }

    }
    depthFirstSearch(maze, row, col)
    return finalMaze
}

function main() {

    let maze = readMaze('input-maze-3.txt')

    let startPosition = findStart(maze)
    let [startX, startY] = startPosition
    console.log('Start position:', startPosition)

    let path = solve(maze, startX, startY)
    console.log('I have found a solution!')
    // console.log(path)
    printMaze(path)
    console.log('fin')
}

main()

Memoize

// TODO:implement a fibonacci function
// TODO: create a memoizer-function
// TODO: memoize fibonacci
const util = require('util')

let memory = {}

function fibonacci(x) {
    if (1 === x || 2 === x) {
       return 1
    }
    return fibonacci(x - 1) + fibonacci(x - 2)
}

function memoize(func) {
    return function (x) {
        if (!memory[x]) {
            memory[x] = func(x)
        }
        return memory[x]
    }
}

function main() {
    let x = 40
    let fast_fibonacci = memoize(fibonacci)
    let answer = fast_fibonacci(x)
    console.log(`f(${x}) = ${answer}`)
    console.log(`Double checking: ${fast_fibonacci(x)}`)
}

main()

File variables

eloquent-javascript-exercises's People

Contributors

amchelle avatar

Watchers

 avatar

eloquent-javascript-exercises's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.