Solutions ()

"use strict";
function countWords(text, words) {
    var texts = text.split(" ");
    var found = [];
    for(var b = 0; b < words.length; b++){
        var foundString = false;
        for(var a = 0; a < texts.length; a++){
            if(texts[a].toLowerCase().indexOf(words[b].toLowerCase()) !== -1){
                foundString = true;
            }
        }
        if(foundString){
            found.push(1);
        }
    }
    return found.length;
}
"use strict";
function angles(a, b, c){
    // First check lengths: http://www.mathwarehouse.com/geometry/triangles/triangle-inequality-theorem-rule-explained.php
    if((a + b > c) && (a + c > b) && (b + c > a)){
        var angles = []; // Array to hold our angles
        var cosA = (Math.pow(b, 2) + Math.pow(c, 2) - Math.pow(a, 2)) / (2 * b * c);
        var A = Math.acos(cosA); // Gives us radians
        var aDegrees = Math.round(A * (180 / Math.PI));
        angles.push(aDegrees);
        var cosB = (Math.pow(c, 2) + Math.pow(a, 2) - Math.pow(b, 2)) / (2 * c * a);
        var B = Math.acos(cosB); // Gives us radians
        var bDegrees = Math.round(B * (180 / Math.PI));
        angles.push(bDegrees);
        var cDegrees = 180 -(aDegrees + bDegrees);
        angles.push(cDegrees);
        angles.sort(sortNumber);
        return angles;
    }else{
        return [0, 0, 0];
    }
}

function sortNumber(a,b) {
    return a - b;
}

var assert = require('assert');
function convert(strNumber, radix) {
    var table = '0123456789abcdefghijklmnopqrstuvwxyz';
    str = strNumber.toLowerCase();
    for (i=0; i<str.length; i++) {
        if (table.indexOf(str[i]) >= radix) {
            return -1;
        }
    }
    if(radix < 37 && radix > 1){
        if(isNaN(parseInt(strNumber, radix))){
            return -1;
        }else{
            return parseInt(strNumber, radix);
        }
    }else{
        return -1;
    }
}
transpose=m=>m[0].map((_,c)=>m.map(r=>r[c]));
"use strict";

function simpleAreas() {
    if(arguments.length === 1){
        return parseFloat(((arguments[0]/2) * (arguments[0]/2) * Math.PI).toFixed(2));
    }
    if(arguments.length === 2){
        return parseFloat((arguments[0] * arguments[1]).toFixed(2));
    }
    if(arguments.length === 3){
        var perimeter = (arguments[0] + arguments[1] + arguments[2])/2;
        return parseFloat((Math.sqrt(perimeter*((perimeter-arguments[0])*(perimeter-arguments[1])*(perimeter-arguments[2])))).toFixed(2));
    }
}
checkLine=(l)=>!l.some((c,i,a)=>~~i&&c===a[i-1]);
"use strict";

function checkGrid(grid) {
    var returnBool = true;
    for(var a = 0; a < grid.length; a++){
        for(var b = 0; b < grid[a].length; b++){
            if(grid[a][b+1] && grid[a][b] == grid[a][b+1]){
                returnBool = false
            }
            if(grid[a+1] && grid[a][b] == grid[a+1][b]){
                returnBool = false
            }
        }
    }
    return returnBool;
}
const fizzBuzz = data => (!(data % 15)) ? "Fizz Buzz" : (!(data % 3)) ? "Fizz" : (!(data % 5)) ? "Buzz" : String(data);
const digitsMultip = data => +(""+data).replace(/0/g,'').split("").reduce((a,b) => ~~a * ~~b, 1);
"use strict";

function mostDifference() {
    if(arguments.length === 0){
        return 0;
    }else{
        var lowest = null;
        var highest = null;
        var difference = null
        for(var i = 0; i < arguments.length; i++){
            if(!lowest || arguments[i] < lowest){
                lowest = arguments[i]
            }
            if(!highest || arguments[i] > highest){
                highest = arguments[i]
            }
            if(!difference || (highest - lowest) > difference){
                difference = highest - lowest;
            }
        }
    }
    return difference;
}
"use strict";

function nonUnique(data) {
    var returnArray = [];
    for(var i = 0; i < data.length; i++){
        if(data.filter(function(value){
            if(isNaN(data[i])){
                return (isNaN(value)) ? value.toUpperCase() === data[i].toUpperCase() : false;
            }else{
                return value === data[i];
            }
        }).length > 1){
            returnArray.push(data[i])
        }
    }
    return returnArray;
}
"use strict";

function swapSort(arr){
    var returnArray = [];
    for(var a = 0; a < arr.length; a++){
        for(var b = 0; b < arr.length; b++){
            if(arr[b+1] && arr[b] > arr[b+1]){
                var temp = arr[b];
                arr[b] = arr[b+1]
                arr[b+1] = temp
                returnArray.push(b+""+(b+1))
            }
        }
    }
    return returnArray.join(",");
}
function countIngots(report) {
    var runningTotal = 0;
    var bits = report.split(",");
    for(var i = 0; i < bits.length; i++){
        runningTotal += ((bits[i].charCodeAt(0) - 65) * 9) + parseInt(bits[i].charAt(1), 10)
    }
    return runningTotal;
}
function countReports(fullReport, fromDate, toDate) {
    var returnTotal = 0;
    var days = fullReport.split("\n");
    var fromDate = new Date(fromDate).getTime();
    var toDate = new Date(toDate).getTime();
    for(var i = 0; i < days.length; i++){
        var dayBits = days[i].split(" ");
        var day = new Date(dayBits[0]).getTime();
        if(day >= fromDate && day <= toDate){
            returnTotal += countIngots(dayBits[1])
        }
    }
    return returnTotal;
}

function countIngots(report) {
    var runningTotal = 0;
    var bits = report.split(",");
    for(var i = 0; i < bits.length; i++){
        runningTotal += ((bits[i].charCodeAt(0) - 65) * 9) + parseInt(bits[i].charAt(1), 10)
    }
    return runningTotal;
}
indexPower=(array,n)=>Math.pow(array[n],n)||-1;
golf=p=>/^((?=.*[a-z])(?=.*[A-Z])(?=.*\d).{10,})$/.test(p);
verifyAnagrams=(f,s)=>f.replace(/ /g,'').toLowerCase().split('').sort().join('')==s.replace(/ /g,'').toLowerCase().split('').sort().join('');
countUnits=number=>(number>>>0).toString(2).match(/1/g).length;
const ALPHABET = "abcdefghijklmnopqrstuvwxyz".split("");
export const checkPangram = text => new Set(text.split("").map(x => x && x.toUpperCase().charCodeAt(0)).filter(x => x >= 65 && x <= 90)).size === 26;
const weakPoint = (matrix) => {
    let i, rowSum;
    const returnObject = {
        "left": null,
        "top": null
    };
    const returnArray = [0, 0];
    for (i = 0; i < matrix.length; i++) {
        rowSum = matrix[i].reduceRight((a, b) => a + b);
        if (!returnObject.left) {
            returnObject.left = rowSum
            returnArray[0] = i;
        } else {
            if (returnObject.left > rowSum) {
                returnObject.left = rowSum
                returnArray[0] = i;
            }
        }
    }
    const newArray = matrix[0].map((_, c) => matrix.map(r => r[c]));
    for (i = 0; i < newArray.length; i++) {
        rowSum = newArray[i].reduceRight((a, b) => a + b);
        if (!returnObject.top) {
            returnObject.top = rowSum
            returnArray[1] = i;
        } else {
            if (returnObject.top > rowSum) {
                returnObject.top = rowSum
                returnArray[1] = i;
            }
        }
    }
    return returnArray;
}
"use strict";

function clockAngle(time){
    var hours = parseInt(time.split(":")[0], 10);
    if(hours > 12){
    hours = hours - 12;
    }
    var minutes = parseInt(time.split(":")[1], 10);
    var hourAngle = 360 * (hours % 12) / 12 + 360 * (minutes / 60) * (1 / 12);
    var minuteAngle = 360 * minutes / 60;
    var difference = (hourAngle - minuteAngle) % 360;
    var difference = (difference < 0) ? difference * -1 : difference;
    return (difference > 180) ? 360 - difference : difference;
}
var o = {
    conjunction:(x,y)=>x&&y,
    disjunction:(x,y)=>x||y,
    implication:(x,y)=>!x||y,
    exclusive:(x,y)=>(x&&!y)||(!x&&y),
    equivalence:(x,y)=>x===y
};
boolean=(x,y,operation)=>o[operation](x,y);
"use strict";

function countInversion(arr){
    var newArray = arr.slice();
    var numberOfInversions = 0;
    var currentNumber = null;
    for(var i = 0; i < newArray.length; i++){
        currentNumber = newArray[i]
        arr.splice(0, 1);
        for(var x = 0; x < arr.length; x++){
            if(currentNumber >= arr[x]){
                numberOfInversions++;
            }
        }
    }
    return numberOfInversions;
}
"use strict";

function evenLast(array){
    if(array.length === 0){
        return 0;
    }else{
        var runningTotal = 0;
        for(var i = 0; i < array.length; i++){
            if(i % 2 === 0){
                runningTotal += array[i];
            }
        }
        return runningTotal * array[array.length -1];
    }
}
"use strict";

function median(data) {
    data.sort(function(a, b){
        return a - b;
    });
    if(data.length % 2){ // ODD
        console.log(data.length / 2);
        return data[Math.floor(data.length / 2)]
    }else{ // EVEN
        console.log(data.length / 2);
        return (data[data.length / 2] + data[(data.length / 2) - 1]) / 2
    }
}
"use strict";
function findMessage(text){
    var returnString = "";
    for(var i = 0; i < text.length; i++){
        if(text.charCodeAt(i) >= 65 && text.charCodeAt(i) <= 90){
            returnString += text.charAt(i)
        }
    }
    return returnString
}
"use strict";

function threeWords(words) {
    var regexObj = /([a-zA-Z]+)\s+([a-zA-Z]+)\s+([a-zA-Z]+)/g;
    return regexObj.test(words)
}
flatList=a=>JSON.stringify(a).replace(/\[/g,'').replace(/\]/g,'').split(",").map(n=>parseInt(n, 10)).filter(i=>!isNaN(i));
"use strict";

function recallPassword(cipherGrille, cipheredPassword) {
    var cG = cipherGrille.map(function(currentValue){
        return currentValue.split("");
    });
    var cP = cipheredPassword.map(function(currentValue){
        return currentValue.split("");
    });
    var returnString = "";
    for(var x = 0; x < 4; x++){
        var ninety = true;
        for(var a = 0; a < cG.length; a++){
            for(var b = 0; b < cG[a].length; b++){
                if(cG[a][b] === "X"){
                    returnString += cP[a][b];
                    if(cP[a][b] === cP[a][b].toUpperCase()){
                        ninety = false;
                    }
                }
            }
        }
        if(ninety){
            rotate90(cG)
        }else{
            for(var y = 0; y < 3; y++){
                rotate90(cG)
            }
        }
    }
    return returnString;
}

function rotate90(matrix){
    var length = matrix.length;
    for(var row = 0; row < (length / 2); row++){
        for(var col = row; col < ( length - 1 - row); col++){
            var tmpVal = matrix[row][col];
            for(var i = 0; i < 4; i++){
                var rowSwap = col;
                var colSwap = (length - 1) - row;
                var poppedVal = matrix[rowSwap][colSwap];
                matrix[rowSwap][colSwap] = tmpVal;
                tmpVal = poppedVal;
                col = colSwap;
                row = rowSwap;
            }
        }
    }
}
golf=c=>c.match(/([A-Z][1-9])/g).reduce((a,b)=>a+(b.charCodeAt(0)-65)*9+b[1]*1,0)
translate=phrase=>phrase.replace(/([b-df-hj-np-tv-xz]{1}[aeiouy]{1})/g,v=>v.charAt(0)).replace(/([aeiouy]{3})/g,v=>v.charAt(0));
function safePawns(p) {
    var safe = 0;
    p.forEach(a=>safe+=([String.fromCharCode(a[0].charCodeAt()-1)+((a[1]*1)-1),String.fromCharCode(a[0].charCodeAt()+1)+((a[1]*1)-1)].filter(n=>p.indexOf(n) != -1).length)?1:0)
    return safe;
}
var ones = Array("", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen");
var tens = Array("", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety");

function tellNumber(num){
    var res = (num < 0) ? ["minus"] : [];
    num = Math.abs(num);
    Math.floor(num/Math.pow(10, 30)) > 0 && res.push(tellNumber(Math.floor(num/Math.pow(10, 30)))+" quintillion");
    num -= Math.floor(num/Math.pow(10, 30)) * Math.pow(10, 30);
    Math.floor(num/Math.pow(10, 24)) > 0 && res.push(tellNumber(Math.floor(num/Math.pow(10, 24)))+" quadrillion");
    num -= Math.floor(num/Math.pow(10, 24)) * Math.pow(10, 24);
    Math.floor(num/Math.pow(10, 18)) > 0 && res.push(tellNumber(Math.floor(num/Math.pow(10, 18)))+" trillion");
    num -= Math.floor(num/Math.pow(10, 18)) * Math.pow(10, 18);
    Math.floor(num/Math.pow(10, 12)) > 0 && res.push(tellNumber(Math.floor(num/Math.pow(10, 12)))+" billion");
    num -= Math.floor(num/Math.pow(10, 12)) * Math.pow(10, 12);
    Math.floor(num/Math.pow(10, 6)) > 0 && res.push(tellNumber(Math.floor(num/Math.pow(10, 6)))+" million");
    num -= Math.floor(num/Math.pow(10, 6)) * Math.pow(10, 6);
    Math.floor(num/1000) > 0 && res.push(tellNumber(Math.floor(num/1000))+" thousand");
    num -= Math.floor(num/1000) * 1000;
    Math.floor(num/100) > 0 && res.push(tellNumber(Math.floor(num/100))+" hundred");
    num -= Math.floor(num/100) * 100;
    var tn = Math.floor(num / 10);
    var one = Math.floor(num % 10);
    if (tn > 0 || one > 0) {
        if (tn < 2) {
            res.push(ones[tn * 10 + one]);
        } else {
            res.push(tens[tn]);
            if (one > 0) {
                res.push(ones[one]);
            }
        }
    }
    if (res.length === 0) {
        res.push("zero");
    }
    return res.join(" ");
}
var push = /(PUSH)/;
var pop = /(POP)/;

function golf(c){
    var A = [], I = 0;
    c.forEach(function(a){
        if(push.test(a)){
            A.push(parseInt(a.split(" ")[1], 10));
        }else{
            if(A.length){
                I += A[A.length - 1]
                if(pop.test(a)){
                    A.pop()
                }
            }
        }
    });
    return I;
}
"use strict";

function countNeighbours(g, r, c) {
    var cs = [],
        I = 0;
    for (var i = 0; i < 3; i++) {
        for (var j = 0; j < 3; j++) {
            var A = [];
            i == 0 && A.push(c - 1);
            i == 1 && A.push(c);
            i == 2 && A.push(c + 1);
            j == 0 && A.push(r - 1);
            j == 1 && A.push(r);
            j == 2 && A.push(r + 1);
            ((A[0] >= 0 && A[0] <= g[0].length - 1) && (A[1] >= 0 && A[1] <= g.length - 1) && (!(A[0] == c && A[1] == r))) && cs.push(A);
        }
    }
    console.log(cs);
    for (var i in cs) {
        (g[cs[i][1]][cs[i][0]]) && I++;
    }
    return I;
}
"use strict";

var R = 6371.00;

function distance(f, s) {
    f = gLL(f), s = gLL(s);
    var dLat = deg2rad(s.lat - f.lat); // deg2rad below
    var dLon = deg2rad(s.lng - f.lng);
    var a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(deg2rad(f.lat)) * Math.cos(deg2rad(s.lat)) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c; // Distance in km
    return d;
}

function deg2rad(deg) {
    return deg * (Math.PI / 180)
}

function gLL(S) {
    var reg = /^(\d+)°(\d+)'(\d+)?([A-Z])[,]*[ ]*(\d+)°(\d+)'(\d+)?([A-Z])$/;
    var d = reg.exec(S);
    return {
        "lat": (d[4] === "S") ? -Math.abs(d[1] * 1 + d[2] / 60 + d[3] / 3600) : d[1] * 1 + d[2] / 60 + d[3] / 3600,
        "lng": (d[8] === "W") ? -Math.abs(d[5] * 1 + d[6] / 60 + d[7] / 3600) : d[5] * 1 + d[6] / 60 + d[7] / 3600
    };
}
"use strict";

function mostLetter(text, allLetters){
    allLetters = allLetters || false;
    if(!allLetters){
        var m = {};
        var l = text.match(/[A-Za-z]/g,'').map(l=>l.toLowerCase()).sort();
        for(i in l){
            (!(l[i] in m)) ? m[l[i]] = 1 : m[l[i]]++;
        }
        return Object.keys(m).reduce(function(a, b){ return m[a] > m[b] ? a : b });
    }else{
        return 0;
    }
}
export const letterQueue = l => l.reduce((r, c) => c.split(" ")[0] === "PUSH" ? r.concat([c.split(" ")[1]]) : r.filter((c, i) =>  i !== 0), []).join("");
"use strict";

function goodRadix(strNumber){
    for(var i = 2; i < 37; i++){
        if(strNumber === parseInt(strNumber, i).toString(i).toUpperCase()){
            if(parseInt(strNumber, i) % (i - 1) === 0){
                return i;
            }
        }
    }
    return 0;
}
"use strict";

function roman(num) {
    if (!+num)
        return false;
    var digits = String(+num).split(""),
        key = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM",
            "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC",
            "","I","II","III","IV","V","VI","VII","VIII","IX"],
        roman = "",
        i = 3;
    while (i--)
        roman = (key[+digits.pop() + (i * 10)] || "") + roman;
    return Array(+digits.join("") + 1).join("M") + roman;
}
"use strict";

var c = ["....", "...-", "..-.", "..--", ".-..", ".-.-", ".--.", ".---", "-...", "-..-"];

function morseTime(timeString) {
    var r = [];
    timeString.match(/([0-9])+/g).map(x => (x.length === 1) ? "0" + x : x).forEach((x, i) => r.push(((i === 0)) ? c[~~x.charAt(0)].slice(2) + " " + c[~~x.charAt(1)] : c[~~x.charAt(0)].slice(1) + " " + c[~~x.charAt(1)]));
    return r.join(" : ");
}
"use strict";

function commonWords(first, second){
    var f = first.split(",");
    var s = second.split(",");
    var n = [];
    for(var i = 0; i < f.length; i++) {
        for(var j = 0; j < s.length; j++) {
            if (f[i] == s[j]) {
                n.push(s[j]);
                break;
            }
        }
    }
    return n.sort().join(",");
}
export const commonWords = (f, s) => f.split(",").filter(w => s.split(",").indexOf(w) !== -1).sort().join(",");
golf=(c,a)=>{
    var a=a/2,A=a*a,c=c/2,C=c*c,pi=Math.PI,x=Math.sqrt(A-C),y=Math.sqrt(C-A);
    return [r(4/3*pi*A*c),a==c?r(4*pi*Math.pow(a,2)):a>c?r(2*pi*a*(a+C/x*h(x/c))):r(2*pi*a*(a+C/y*Math.asin(y/c)))]
}
r=n=>Math.round(n*100)/100
h=x=>Math.log(x+Math.sqrt(x*x+1))
"use strict";

hamming=(n, m)=>p(n,20).split("").reduceRight((a,b,i)=>a+(p(n,20).split("")[i] !== p(m,20).split("")[i]),0);
p=(n, w)=>Array.apply(null, Array(w-n.toString(2).length+1)).map(Number.prototype.valueOf,0).join("") + n.toString(2);
const hammingDistance = (n, m) => ((n ^ m).toString(2).replace(/0/g, '').length);
circleEquation=(n)=>{
    var p=n.match(/\((\d+),(\d+)\),\((\d+),(\d+)\),\((\d+),(\d+)\)/),a=[],b=[],c=[];a[0]=~~p[1],a[1]=~~p[2],b[0]=~~p[3],b[1]=~~p[4],c[0]=~~p[5],c[1]=~~p[6],e=k(a,b,c);
    return "(x-"+r(e[0])+")^2+(y-"+r(e[1])+")^2="+r(d(a, e))+"^2"
}
k=(b,c,d)=>{
    var temp=s(c[0])+s(c[1]),bc=(s(b[0])+s(b[1])-temp)/2,cd=(temp-s(d[0])-s(d[1]))/2,det=(b[0]-c[0])*(c[1]-d[1])-(c[0]-d[0])*(b[1]-c[1]);
    return [(bc*(c[1]-d[1])-cd*(b[1]-c[1]))/det,((b[0]-c[0])*cd-(c[0]-d[0])*bc)/det];
}
s=a=>a*a;
d=(a,b)=>Math.sqrt(s(a[0]-b[0])+s(a[1]-b[1]));
r=n=>Math.round(n*100)/100;
golf=g=>(g.length==1||g[0][0][0]!=g[1][0][0]&&golf(g.slice(1,g.length)))&&h(g[0]);
h=g=>(g.length==1||g[0][0]!=g[1][0]&&h(g.slice(1,g.length)))&&i(g[0]);
i=g=>g.length==1||g[0]!=g[1]&&i(g.slice(1,g.length));
myMax=(a,b)=>(a>b)?a:b;
rotateList=(e, r)=>{
    while(r--){
        e.push(e.shift());
    }
    return e;
}
sureNot=l=>(l.startsWith('not '))?l:"not "+l;
twoMonkeys=(a,b)=>a===b;
function listCombination(arr1, arr2) {
    var arr = [];
    for(var i = 0; i < arr1.length; i++){
        arr.push(arr1[i]);
        arr.push(arr2[i]);
    }
    return arr;
}
strLength=l=>l.length;
var pure_numbers = [
    [ // 0
        [1,1,0],
        [1,0,1],
        [1,0,1],
        [1,0,1],
        [0,1,1],
    ],
    [ // 1
        [0,1,0],
        [1,1,0],
        [0,1,0],
        [0,1,0],
        [0,1,0],
    ],
    [ // 2
        [1,1,1],
        [0,0,1],
        [0,1,1],
        [1,0,0],
        [1,1,1],
    ],
    [ // 3
        [1,1,1],
        [0,0,1],
        [0,1,0],
        [0,0,1],
        [1,1,1],
    ],
    [ // 4
        [1,0,1],
        [1,0,1],
        [1,1,1],
        [0,0,1],
        [0,0,1],
    ],
    [ // 5
        [1,1,1],
        [1,0,0],
        [1,1,0],
        [0,0,1],
        [1,1,0],
    ],
    [ // 6
        [0,1,1],
        [1,0,0],
        [1,1,1],
        [1,0,1],
        [0,1,1],
    ],
    [ // 7
        [1,1,1],
        [0,0,1],
        [0,1,0],
        [1,0,0],
        [1,0,0],
    ],
    [ // 8
        [1,1,1],
        [1,0,1],
        [1,1,1],
        [1,0,1],
        [1,1,1],
    ],
    [ // 9
        [0,1,1],
        [1,0,1],
        [1,1,1],
        [0,0,1],
        [1,1,0],
    ]
], index = 0;
recognize=(a)=>{
    var returnInt = "";
    var numbers = [];
    for(var y = 0; y < a.length; y++){
        var index = 0;
        while(a[y].length > 1){
            a[y].shift();
            if(!numbers[index]){
                numbers[index] = [];
            }
            numbers[index].push(a[y].splice(0,3));
            index++;
        }
    }
    for(var i = 0; i < numbers.length; i++){
        var this_num = JSON.stringify(numbers[i]).replace(/\[/g, "").replace(/\]/g, "");
        for(var a = 0; a < pure_numbers.length; a++){
            var that_num = JSON.stringify(pure_numbers[a]).replace(/\[/g, "").replace(/\]/g, "");
            if(differences(this_num, that_num) < 2){
                returnInt += a;
            }
        }
    }
    return ~~returnInt;
}
differences=(a, b)=>a.split(",").reduceRight((p,c,i)=>p+(c!==b.split(",")[i]),0);
function correctSentence(text: string): string {
    return text.replace(/^([a-zA-Z])/, x => x.toUpperCase()).replace(/([^.])$/, '$1.');;
}
function leftJoin(phrases: string[]): string {
    return phrases.map(c => c.replace(/right/gi, 'left')).join(",");
}
function reverseRoman(roman) {
    const nums = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000};
    return roman.split("").reduce((t, c, i, a) => (i === 0) ? nums[c] : (nums[c] <= nums[a[i-1]]) ? t + nums[c] : t - nums[a[i-1]]*2 + nums[c], 0);
}
function findMessage(data) {
    return data.replace(/[^A-Z]/g, '');
}
function median(data: number[]) {
    return data.length % 2
    	? data.sort((a, b) => a - b)[Math.floor(data.length / 2)]
    	: (data.sort((a, b) => a - b)[data.length / 2] + data.sort((a, b) => a - b)[(data.length / 2) - 1]) / 2;
}
const easyUnpack = elements => [elements[0], elements[2], elements[elements.length - 2]];
const follow = i => [
        i.split('').reduce((t, c) => t + (c == "r" ? 1 : c == "l" ? -1 : 0), 0),
        i.split('').reduce((t, c) => t + (c == "f" ? 1 : c == "b" ? -1 : 0), 0)
    ];
const multTwo = (a, b) => a * b;
const middle = s => s.substr(s.length - 1 >>> 1, (~s.length & 1) + 1);
const sayHi = (name, age) => `Hi. My name is ${name} and I'm ${age} years old`;
const morseEncoder = text => text.toLowerCase().split('').map(x => MORSE[x] || ' ').join(' ');
const groupEqual = els => els.reduce(function(t,c,i,a){
    if(t.length === 0 || c !== t[t.length - 1][0]){
        t.push([c])
    }else{
        t[t.length - 1].push(c)
    }
    return t;
}, []);
function brackets(expression: string): boolean{
    var parentheses = "[]{}()",
        stack = [],
        i, character, bracePosition;

    for(i = 0; character = expression[i]; i++) {
        bracePosition = parentheses.indexOf(character);

        if(bracePosition === -1) {
        continue;
        }

        if(bracePosition % 2 === 0) {
        stack.push(bracePosition + 1); // push next expected brace position
        } else {
        if(stack.length === 0 || stack.pop() !== bracePosition) {
            return false;
        }
        }
    }

    return stack.length === 0;
}
function unluckyDays(year) {
    const d = new Date();
    let counter = 0;
    for(let month = 0; month < 12; month++){
        d.setFullYear(year, month, 13);
        if (d.getDay() == 5){
            counter++;
        }
    }
    return counter;
}
const bestStock = table => Object.entries(table).map((o, i) => ({s: o[0], v: o[1]})).sort((a, b) => ~~b.v - ~~a.v)[0].s;
const toCamelCase = (n) => n.charAt(0).toUpperCase() + n.slice(1, n.length).toLowerCase().trim().split(/[.\-_\s]/g).reduce((s, w) => s + w[0].toUpperCase() + w.slice(1));
const absoluteSorting = numbers => numbers.sort((a, b) => Math.abs(a) - Math.abs(b));
const sunAngle = dayTime => ((~~(dayTime.split(":")[0]) - 6) < 0)
    ? "I don't see the sun!"
    : (~~(dayTime.split(":")[0]) - 6) + (~~(dayTime.split(":")[1]) / 60) > 12
        ? "I don't see the sun!"
        : (((~~(dayTime.split(":")[0]) - 6) + (~~(dayTime.split(":")[1]) / 60)) / 12) * 180;
const OPERATION_NAMES = {
    "conjunction": (a, b) => a && b,
    "disjunction": (a, b) => a || b,
    "implication": (a, b) => !a || b,
    "exclusive": (a, b) => a ? !b : b,
    "equivalence": (a, b) => a === b
}

const boolean = (x, y, operation) => OPERATION_NAMES[operation](x, y);
const allTheSame = elements => new Set(elements).size <= 1;
const morseDecoder = code => code.split("  ").map(c => c.split(" ").map(x => MORSE[x]).join('')).join(" ").charAt(0).toUpperCase() + code.split("  ").map(c => c.split(" ").map(x => MORSE[x]).join('')).join(" ").slice(1);
const fromCamelCase = n => n.split(/(?=[A-Z])/g).join("_").toLowerCase();
function worthOfWords(words: string[]): string {
    return Array.from(words, word => ({word: word, score: word.split("").reduce((a, c) => a + VALUES[c], 0)})).sort((a, b) => a.score - b.score).reverse()[0].word;
}
function endOfOther(name) {
    return !!~name.findIndex(function(c, i, a) {
        let returnVal = false;
        for(let x = 0; x < a.length; x++){
            if(x !== i && a[x].endsWith(c)){
                    returnVal = true;
            }
        }
        return returnVal;
    });
}
function digitStack(c: string[]): number {
    const push = /(PUSH)/;
    const pop = /(POP)/;
    const A = [];
    let I = 0;
    c.forEach(function(a){
        if(push.test(a)){
            A.push(~~a.split(" ")[1]);
        }else{
            if(A.length){
                I += A[A.length - 1]
                if(pop.test(a)){
                    A.pop()
                }
            }
        }
    });
    return I;
}
export const daysDiff = (a, b) => Math.abs((new Date(a.map((c,i) => c.toString().padStart(i === 0 ? 4 : 2, "0")).join("-")).getTime() - new Date(b.map((c,i) => c.toString().padStart(i === 0 ? 4 : 2, "0")).join("-")).getTime()) / 86400000);
export const longestPalindromic = s => {
    if(s === s.split('').reverse().join('')) return s;
    let charArray = [], 
    countArray = [];
    let currentWord = s[0];
    let count = 1;
    let sLength = s.length+1;
    //build array of repeating characters
    for(let i=1; i<sLength; i++) {
        if(s[i] === s[i-1]) {
            //simply advance by incrementing count and character to currentWord
            count++;
            currentWord += s[i];
        } else { //different character found
            //save character & count
            countArray.push(count);
            charArray.push(currentWord);
            
            //reset currentWord, count
            currentWord = s[i];
            count = 1;
        }
    }
    let head = 0;
    let tail = 0;
    let maxWord = '';
    let charLength = charArray.length;
    //step through character array to check for characters surrounding repeated characters
    for(let k=0; k<charLength; k++){
        currentWord = charArray[k];
        tail = head + countArray[k] - 1;
        let steps = sLength-countArray[k]; //num of steps we need to take surrounding repeated characters
        for(let l=1; l<steps; l++){
            if(s[head-l] === s[tail+l]) {
                currentWord = s[head-l] + currentWord + s[tail+l];
            } else {
                //check currentWord against maxWord
                maxWord = maxWord.length < currentWord.length ? currentWord : maxWord;
                head = tail+1;
                break;
            }
        }
    }
    return maxWord;
}
export const betweenMarkers = (t, b, e) => (
    ((!~t.indexOf(b)) ? 0 : t.indexOf(b) + b.length) > 
    ((!~t.indexOf(e)) ? t.length : t.indexOf(e)))
        ? "" 
        : t.substring(
            ((!~t.indexOf(b)) ? 0 : t.indexOf(b) + b.length), 
            ((!~t.indexOf(e)) ? t.length : t.indexOf(e))
        );
    
export const firstWord = a => a.split("").reduce(function(a, c, i, arr){
    if(!a.s){
        if(c !== " " && c !== "," && c !== "."){
            a.s = true;
            a.w = c
        }
    } else {
        c !== " " && c !== "," && c !== "." ? a.w += c : arr.splice(1);
    }
    return a;
}, {
    w: "",
    s: false
}).w;
export const biggerPrice = (a, b) => b.sort((x, y) => x.price - y.price).reverse().slice(0, a);
export const timeConverter = a => new Date('1970-01-01T' + a + 'Z').toLocaleTimeString('en-GB', {
    timeZone: 'UTC',
    hour12: true,
    hour: 'numeric',
    minute: 'numeric'
}).replace("AM", "a.m.").replace("PM", "p.m.");
export const friday = a => (12 - new Date([a.split(".")[1], a.split(".")[0], a.split(".")[2]].join("/")).getDay()) % 7;
export const twoTeams = a => {
    const ships = [[], []];
    const keys = Object.keys(a);
    for (let i = 0; i < keys.length; i++) {
        ships[a[keys[i]] < 20 || a[keys[i]] > 40 ? 0 : 1].push(keys[i]);
    }
    ships[0].sort();
    ships[1].sort();
    return ships;
}
export const countInversion = s => s.map((e, i) => s.filter((e2, i2) => (i2 > i) && (e2 < e)).length).reduce((a, b) => a + b);
export const mostFrequentDays = a => {
    let d = new Date(new Date(new Date().getFullYear(), 0, 1).setFullYear(a))
    const days = [
        {d:"Sunday",    n:0, i: 6},
        {d:"Monday",    n:0, i: 0},
        {d:"Tuesday",   n:0, i: 1},
        {d:"Wednesday", n:0, i: 2},
        {d:"Thursday",  n:0, i: 3},
        {d:"Friday",    n:0, i: 4},
        {d:"Saturday",  n:0, i: 5}
    ];
    while(d.getFullYear() === a){
        days[d.getDay()].n++;
        d.setDate(d.getDate() + 1);
    }
    return days.filter(function(a){ 
        return a.n === Math.max(...days.map(o => o.n))
    }).sort((a, b) => a.i - b.i).map(a => a.d);
};
export const navigation = a => {
    const getIndexOfK = (arr, k) => {
        for (let i = 0; i < arr.length; i++) {
            const index = arr[i].indexOf(k);
            if (index > -1) {
                return [i, index];
            }
        }
    };
    const d = (a, b) => Math.max(Math.abs(b[0] - a[0]), Math.abs(b[1] - a[1]));
    return d(getIndexOfK(a, "Y"), getIndexOfK(a, "C")) + 
            d(getIndexOfK(a, "Y"), getIndexOfK(a, "M")) + 
            d(getIndexOfK(a, "Y"), getIndexOfK(a, "S"));
}
export const safeCode = equation => {
    const numbers = [...Array(10).keys()].map(x => x.toString()).filter(x => !new Set(equation.replace(/\D/g, '').split("")).has(x));
    for(let i = 0; i < numbers.length; i++){
        try{
            if(eval(equation.split("=")[0].replace(new RegExp("#", "g"), numbers[i])) === eval(equation.split("=")[1].replace(new RegExp("#", "g"), numbers[i]))){
                return ~~numbers[i];
            }            
        }
        catch(error){
            continue;
        }
    }
    return -1;
}
export const countConsecutiveSummers = n => {
    let c = 0;
    let x = 1;
    while (x * (x + 1) < 2 * n) {
        let y = (1 * n - (x * (x + 1)) / 2);
        let a = y / (x + 1);
        if (!(a - ~~a)) {
            c++;
        }
        x++;
    }
    return c + 1;
}
export const repeatInside = a => {
    let result = "";
    for (let i = 0; i < a.length; i++) {
        for (let j = 0; j < a.length - i; j++) {
            let s = a.substring(i, i + j + 1);
            for (let k = 2; k < Math.floor(a.length / s.length) + 1; k++) {
                let ls = s.repeat(k);
                if (!!~a.indexOf(ls) && ls.length > result.length) {
                    result = ls;
                }
            }
        }
    }
    return result;
}
export const friendlyNumber = (n, { base = 1000, decimals = 0, suffix = "", powers = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] } = {}) => {
    for (var e = 0; e < powers.length; e++) {
        if (Math.abs(n) < Math.pow(base, e + 1)) break;
    }
    e = Math.min(e, powers.length - 1);
    n /= Math.pow(base, e);
    if (!decimals) {
        n = n < 0 ? -Math.floor(-n) : Math.floor(n);
    }
    return n.toFixed(decimals) + powers[e] + suffix;
}
export const toEncrypt = (str, amount) => {
    // Wrap the amount
    if (amount < 0)
        return toEncrypt(str, amount + 26);
    // Make an output variable
    var output = '';
    // Go through each character
    for (var i = 0; i < str.length; i++) {
        // Get the character we'll be appending
        var c = str[i];
        // If it's a letter...
        if (c.match(/[a-z]/i)) {
            // Get its code
            var code = str.charCodeAt(i);
            // Uppercase letters
            if ((code >= 65) && (code <= 90))
                c = String.fromCharCode(((code - 65 + amount) % 26) + 65);
            // Lowercase letters
            else if ((code >= 97) && (code <= 122))
                c = String.fromCharCode(((code - 97 + amount) % 26) + 97);
        }
        // Append
        output += c;
    }
    // All done!
    return output;
};
const evenLast = d => d.length === 0 ? 0 : d.filter((a, i) => i % 2 === 0).reduce((a, b) => a + b, 0) * d[d.length - 1];
export const subnetworks = (n, c) => {
    const singles = [];
    const multiples = new Set();
    for(let x of n){
        for(let y of c){
            if(!!~x.indexOf(y)){
                x.splice(x.indexOf(y), 1);
            }
            if(x.length === 1){
                singles.push(x);
            }else{
                if(x.length > 1){
                    multiples.add(JSON.stringify(x.sort()));
                }
            }
        }
    }
    multiples.forEach(x => {
        for(let y = singles.length - 1; y >= 0; y--){
            if(!!~JSON.stringify(x).indexOf(singles[y][0])){
                singles.splice(y, 1);
            }
        }
    });
    return singles.filter(e => e.length).length + multiples.size;
}
export const symmetric = matrix => {
    for(const [j, v] of matrix.entries()){
        for(const [i, v] of matrix.entries()){
            if(matrix[j][i] !== ~matrix[i][j] + 1){
                return false;    
            }
        }
    }
    return true;
}
export const capture = data => {
    const infected = data[0];
    const target = Array.from({length: data.length}, (_, i) => data[i][i]);
    let time = 0;
    while(!target.every(el => !el)) {
        for(const [i, v] of target.entries()){
            if (infected[i] === 1 && v > 0) {
                target[i]--;
            }
        }
        for(const [i, v] of target.entries()){
            if (!v) {
                for (const[j, v] of data[i].entries()) {
                    if (v === 1 && !infected[j]) {
                        infected[j] = 1;
                    }
                }
            }
        }
        time++;
    }
    return time;
}
export const secondIndex = (t, s) => t.indexOf(s,t.indexOf(s) + 1) < 0 ? undefined : t.indexOf(s,t.indexOf(s) + 1);
const nonUniqueElements = d => d.filter(c => d.indexOf(c) !== d.lastIndexOf(c));
const findKey = a => !!~a.toLowerCase().indexOf("key");
const genArrZero = num => Array(num).fill(0);
export const arrSize = (els: number[]): number => els.length;
const totalCost = (calls) => {
    const o = {};
    let t = 0;
    calls.forEach(c => {
        const d = c.split(" ")[0], 
                s = Math.ceil(~~c.split(" ")[2] / 60);
        o[d] = (d in o) ? o[d] + s : s;
    });
    for (const p in o) {
        t += (o[p] > 100) ? 100 + (o[p] - 100) * 2 : o[p];
    }
    return t
}
export const makingChange = (total, coins) => {
    /**
     * Bottom up way of solving this problem.
     * Keep input sorted. Otherwise temp[j-arr[i]) + 1 can become Integer.Max_value + 1 which
     * can be very low negative number
     * Returns Integer.MAX_VALUE - 1 if solution is not possible.
     */
    const T = [...Array(total + 1).keys()].map(x => !x ? x : Infinity - 1)
    const R = [...Array(total + 1).keys()].map(x => -1)
    for (let j = 0; j < coins.length; j++) {
        for (let i = 1; i <= total; i++) {
            if (i >= coins[j]) {
                if (T[i - coins[j]] + 1 < T[i]) {
                    T[i] = 1 + T[i - coins[j]];
                    R[i] = j;
                }
            }
        }
    }
    return T[total];
}
export function highestBuilding(rows) {
    let ret = null;
    rows.forEach((row, index, arr) => {
        if (!ret && row.includes(1)) {
            ret = [row.indexOf(1) + 1, arr.length - index];
        }
    })
    return ret;
}
const StringReduction = str => {
  const a = str.split('')
  let i = a.length
  while (i--) {
    if (a[i - 1] !== a[i]) {
      a.splice(i - 1, 2, ['a', 'b', 'c'].filter(el => el !== a[i - 1] && el !== a[i])[0])
      i = i ? a.length - 1 : i
    }
  }
  return a.length
}
console.log("cccc", StringReduction("cccc"));
console.log("abcabc", StringReduction("abcabc"));
/*
 * Names regex groups are really handy! Remember to end a regex with a ";"!
 */
const timeRegex = /(?<sHour>\d{1,2})(\:(?<sMinute>\d{1,2}))?\s(?<sAmPm>am|pm)\s\-\s(?<eHour>\d{1,2})(\:(?<eMinute>\d{1,2}))?\s(?<eAmPm>am|pm)/;
const daysRegex = /\b([a-zA-Z]{3,4}\-?)\b/g;
/*
 * Our tests:
 */
const tests = [
  "Mon-Sun 11:00 am - 10 pm",
  "Mon-Sun 11 am - 12 am",
  "Mon-Thu, Sat 11 am - 9 pm / Fri 5 pm - 9 pm",
  "Mon-Fri, Sat 11 am - 12 pm / Sun 11 am - 10 pm",
  "Mon-Thu, Sun 11:30 am - 10 pm / Fri-Sat 11:30 am - 11 pm",
  "Mon-Thu 11 am - 11 pm / Fri-Sat 11 am - 12:30 am / Sun 10 am - 11 pm"
]
/*
 * Our original object
 */
const daysObj = { "Mon": "", "Tues": "", "Wed": "", "Thu": "", "Fri": "", "Sat": "", "Sun": "" }
/*
 * Our array of days from the object above
 */
const days = Object.keys(daysObj)
/*
 * Our function to format a time
 */
const formatTime = (hour, minute, AmPm) => `${hour}:${minute} ${AmPm}`
/*
 * Our function to format a time duration
 */
const generateTime = (sHour, sMinute, sAmPm, eHour, eMinute, eAmPm) => {
  const sTime = formatTime(sHour, sMinute, sAmPm)
  const eTime = formatTime(eHour, eMinute, eAmPm)
  return `${sTime} - ${eTime}`
}
/*
 * Iterate over the tests
 */
for (const test of tests) {
  /*
   * Start with a fresh version of the days object by copying the one from above.
   */
  const returnObj = Object.assign({}, daysObj)
  /*
   * First we need to chunks of the string seperated by " / "
   * We'll then iterate over each chunk.
   */
  for (chunk of test.split(" / ")) {
    /*
     * We'll then get all the days from the chunk.
     */
    const daysResult = chunk.match(daysRegex)
    /*
     * We'll then destructure the groups from the regex match. Named regex groups are really helpful for this as we
     * we can then access the values by name from the groups object, and have default values for those that might be 
     * undefined.
     */
    const { sHour, sMinute = '00', sAmPm, eHour, eMinute = '00', eAmPm } = timeRegex.exec(chunk.trim()).groups
    /*
     * We'll then generate the time from the values we've extracted from the regex match.
     */
    const timeString = generateTime(sHour, sMinute, sAmPm, eHour, eMinute, eAmPm)
    /*
     * We'll then iterate over the days we've extracted from the chunk.
     */
    for (let i = 0; i < daysResult.length; i++) {
      /*
       * If the last character of the day is a hyphen, we know we need to iterate over the days array we created above.
       */
      if (daysResult[i].charAt(daysResult[i].length - 1) === "-") {
        /*
         * We'll then iterate over the days array we created above and populate it with the time string we've generated.
         */
        for (let l = days.findIndex(e => e === daysResult[i].slice(0, -1)); l < days.length; l++) {
          if (days[l] !== daysResult[i + 1]) {
            returnObj[days[l]] = timeString
          } else {
            /*
             * If the current day isn't the same as the next day in the array, we'll break.
             */
            break;
          }
        }
      } else {
        /*
         * If the last character of the day is not a hyphen, we can just set taht day with the time string we've 
         * generated.
         */
        returnObj[daysResult[i]] = timeString
      }
    }
  }
  /*
   * Display the result alng with the test
   */
  console.log(test, JSON.stringify(returnObj, null, 2))
}
const add = (...a) => a.reduce((t, v) => t + v)
const allLongestStrings = a => a.filter(i => i.length === Math.max(...(a.map(a => a.length))))
const allLongestStrings = (a, i = Math.max(...(a.map(a => a.length)))) => a.filter(e => e.length === i)
const arrayReplace = (arr, o, n) => arr.map(e => e === o ? n : e)
const caseInsensitivePalindrome = (s) => s.toLowerCase().replace(/[\W_]/g, '') === s.toLowerCase().replace(/[\W_]/g, '').split('').reverse().join('')
const caseInsensitivePalindrome = s => [...s = s.toLowerCase()].reverse().join`` === s;
const encloseInBrackets = s => `(${s})`
const encloseInBrackets = s => ['(', s, ')'].join('')
const encloseInBrackets = s => ['('].concat(s).concat(')').join('')
const encloseInBrackets = s => '('.concat(s, ')')
const encloseInBrackets = s => [...s.split('')].map((c, i, a) => i === 0 ? `(${c}` : i === a.length - 1 ? `${c})` : c).join('')
const encloseInBrackets = s => String.fromCharCode(40, ...s.split('').map((_, i) => s.charCodeAt(i)), 41);
const factorialNumber = n => n ? n * factorialNumber(n - 1) : 1
const firstDigit = s => s.match(/\d/)[0]
const largestNumber = n => ~~[...Array(n)].fill(9).join``
const maxMultiple = (d, b) => ~~(b/d) * d
const maxMultiple = (d, b) => b - (b % d)
const maxMultiple = (d, b) => Math.floor(b/d) * d // works
const maxMultiple = (d, b) => parseInt(b/d, 10) * d // works
export const timeConverter = a => {
  let [, h, m, mod] = a.match(/(\d?\d):(\d\d)\s*([a|p].m.)/);
  h = h === "12" ? `0` : h;
  h = mod === "p.m." ? `${~~h + 12}` : h;
  h = h.length === 1 ? `0${h}` : h;
  return `${h}:${m}`;
}
const candies = (children, candy) => Math.floor(candy / children) * children
const depositProfit = (d, r, t) => {
    let y = 0
    while (d <= t) {
        y++
        d += (r / 100) * d
    }
    return y
}
const chunkyMonkey = (values, size) => {
  var arr = []
  for (let i = 0, len = values.length; i < len; i += size){
    arr.push(values.slice(i, i + size))
  }
  return arr
}
const centuryFromYear = num => Math.floor((!(num % 100) ? num - 1 : num) / 100) + 1
//const reverseAString = str => str.split("").reverse().join("")
const reverseAString = (str) => str === "" ? "" : reverseAString(str.substr(1))  + str.charAt(0)
const sortByLength = strs => strs.sort((a, b) => a.length - b.length)
const countVowelConsonant = str => str.split("").reduce((a, c) => a + (!!~['a','e','i','o','u'].indexOf(c) ? 1 : 2), 0)
body {
  background-color: #eee; }

#view[data-value="1"] > .dice {
  transform: rotateY(360deg) !important; }

#view[data-value="2"] > .dice {
  transform: rotateY(-90deg) !important; }

#view[data-value="6"] > .dice {
  transform: rotateY(180deg) !important; }

#view[data-value="4"] > .dice {
  transform: rotateY(90deg) !important; }

#view[data-value="3"] > .dice {
  transform: rotateX(-90deg) !important; }

#view[data-value="5"] > .dice {
  transform: rotateX(90deg) !important; }

#view {
  cursor: pointer;  
  width: 200px;
  height: 200px;
  margin: 100px;
  perspective: 600px; }
  #view .dice {
    width: 200px;
    height: 200px;
    position: absolute;
    transform-style: preserve-3d;
    transition: transform 1s; }
    #view .dice .side {
      position: absolute;
      width: 200px;
      height: 200px;
      background: #fff;
      box-shadow: inset 0 0 40px #ccc;
      border-radius: 40px; }
      #view .dice .side.inner {
        background: #e0e0e0;
        box-shadow: none; }
      #view .dice .side.front {
        transform: translateZ(100px); }
        #view .dice .side.front.inner {
          transform: translateZ(98px); }
      #view .dice .side.right {
        transform: rotateY(90deg) translateZ(100px); }
        #view .dice .side.right.inner {
          transform: rotateY(90deg) translateZ(98px); }
      #view .dice .side.back {
        transform: rotateY(180deg) translateZ(100px); }
        #view .dice .side.back.inner {
          transform: rotateX(-180deg) translateZ(98px); }
      #view .dice .side.left {
        transform: rotateY(-90deg) translateZ(100px); }
        #view .dice .side.left.inner {
          transform: rotateY(-90deg) translateZ(98px); }
      #view .dice .side.top {
        transform: rotateX(90deg) translateZ(100px); }
        #view .dice .side.top.inner {
          transform: rotateX(90deg) translateZ(98px); }
      #view .dice .side.bottom {
        transform: rotateX(-90deg) translateZ(100px); }
        #view .dice .side.bottom.inner {
          transform: rotateX(-90deg) translateZ(98px); }
      #view .dice .side .dot {
        position: absolute;
        width: 46px;
        height: 46px;
        border-radius: 23px;
        background: #444;
        box-shadow: inset 5px 0 10px #000; }
        #view .dice .side .dot.center {
          margin: 77px 0 0 77px; }
        #view .dice .side .dot.dtop {
          margin-top: 20px; }
        #view .dice .side .dot.dleft {
          margin-left: 134px; }
        #view .dice .side .dot.dright {
          margin-left: 20px; }
        #view .dice .side .dot.dbottom {
          margin-top: 134px; }
        #view .dice .side .dot.center.dleft {
          margin: 77px 0 0 20px; }
        #view .dice .side .dot.center.dright {
          margin: 77px 0 0 134px; }
const fib = n => {
    const arr = [0, 1]
    let i = 1
    while(arr[arr.length - 1] <= n){
        arr.push(arr[arr.length - 2] + arr[arr.length - 1])
        i++
    }
    arr.pop()
    return arr
}

const sumOddFibonacciNumbers = num => fib(num).reduce((a, c) => Math.abs(c % 2) === 1 ? c + a : a, 0)
const byTwo = a => {
    const r = []
    for(let i = 0; i < a.length; i++){
        if(i < a.length - 1 ){
            r.push([a[i], a[i + 1]])
        }
    }
    return r
}

const adjacentElementsProduct = nums => Math.max(...byTwo(nums).map(e => e[0] * e[1]))
const avoidObstacles = nums => {
  let n = 2,
      found = false
  while (!found) {
    if (nums.every(num => num % n !== 0)) {
      found = true
    } else {
      n++
    }
  }
  return n
}
const validTime = str => parseInt(str.split(":")[0], 10) >= 0 && parseInt(str.split(":")[0], 10) <= 24 && parseInt(str.split(":")[1], 10) >= 0 && parseInt(str.split(":")[1], 10) < 60 
// const validTime = str => ~~str.split(":")[0] >= 0 && ~~str.split(":")[0] <= 24 && ~~str.split(":")[1] >= 0 && ~~str.split(":")[1] < 60 
// In the 24-hour time notation, the day begins at midnight, 00:00, and the last minute of the day begins at 23:59. Where convenient, the notation 24:00 may also be used to refer to midnight at the end of a given date[5] — that is, 24:00 of one day is the same time as 00:00 of the following day.
const extractEachKth = (nums, index) => nums.filter((_,i) => (i + 1) % index)
const byTwo = a => {
    const r = []
    for(let i = 0; i < a.length; i++){
        if(i < a.length - 1 ){
            r.push([a[i], a[i + 1]])
        }
    }
    return r
}
const arrayMaximalAdjacentDifference = nums => Math.max(...byTwo(nums).map(a => Math.abs(a[0] - a[1])))
const previous = document.querySelector(".previous")
const next = document.querySelector(".next")
const gallery = document.querySelector(".gallery")
const cards = Array.from(document.querySelectorAll(".card"))
const matrixR = /matrix\(\s*\d+,\s*\d+,\s*\d+,\s*(\-*\d+),\s*\d+,\s*\d+\)/

gallery.style.transform = window.getComputedStyle(gallery).transform

next.addEventListener('click', e => {
  let current = null
  cards.forEach((c, i) => {
    if(c.classList.contains('current')){
      current = i
    }
  })
  if(current < cards.length - 1){
    cards[current].classList.remove('current')
    cards[current + 1].classList.add('current')
    gallery.style.transform = `matrix(1, 0, 0, 1, ${-220 * (current + 1)}, 0)`
    previous.style.opacity = 1
    if(current + 1 === cards.length - 1){
      next.style.opacity = 0.3
    }
  }
})

previous.addEventListener('click', e => {
  let current = null
  cards.forEach((c, i) => {
    if(c.classList.contains('current')){
      current = i
    }
  })
  if(current > 0){
    cards[current].classList.remove('current')
    cards[current - 1].classList.add('current')
    gallery.style.transform = `matrix(1, 0, 0, 1, ${-220 * (current - 1)}, 0)`
    next.style.opacity = 1
    if(current - 1 === 0){
      previous.style.opacity = 0.3
    }
  }
})
const insertDashes = arr => arr.split('').map((c, i, a) => c === ' ' ? ' ' : a[i+1] === ' ' ? c : i < a.length - 1 ? `${c}-` : c ).join('')
const differentSymbolsNaive = str => new Set(str.split('')).size

The byTwo function I used in Days 10 and 14 can be re-written like this:

[1,2,3,4,5,6].map((c, i, a) => a[i+1] && [c, a[i+1]]).filter(e => Array.isArray(e))

Much nicer, and means that Day 10 can be written like this:

const adjacentElementsProduct = nums => Math.max(...nums.map((c, i, a) => a[i+1] && [c, a[i+1]]).filter(e => Array.isArray(e)).map(e => e[0] * e[1]))

With Day 14 written like this:

const arrayMaximalAdjacentDifference = nums => Math.max(...nums.map((c, i, a) => a[i+1] && [c, a[i+1]]).filter(e => Array.isArray(e)).map(a => Math.abs(a[0] - a[1])))

There was mention of a for loop in the description, but map seemed the most suited to this one. I'm really not sure why, but I soirt of get a kick out of using c,i,a as the arguments. c is the current array element, i is the index of that element in the (a) array. Works, doesn't it?

const arrayPreviousLess = nums => nums.map((c,i,a) => !i ? -1 : a[i-1] < c ? a[i-1] : -1)

Or shrunk:

const arrayPreviousLess=n=>n.map((c,i,a)=>!i?-1:a[i-1]<c?a[i-1]:-1)

After playing with it some more, I clocked that the byTwo refactor above was a bit pants. We return the appropriately chunked array, but only after removing the extraneous element with the filter - this seems inefficient to me. I got to thinking about using a reduce function instead but got into all sorts of issues trying to return the array after pushing the new element. I had problems because I'd forgotten that push returns the length of the array after the addition rather than the array with the new element. That's where concat came to the rescue, now we have:

[1,2,3,4,5,6].reduce((n,c,i,a)=>(a[i+1])?n.concat([[c,a[i+1]]]):n,[])

Much cleaner, but it messes up my c,i,a, especially as the first value should be another a, to represent the accumulator. Ah well, nothing's perfect I guess, and a,c,i,a won't work. Replacing the first a with n seems to work OK though.

That was a fun one, mainly because I wanted to try alternative ways of solving it, and ways of solving it which didn't use charCodeAt or a Set.

const alphabetSubsequence = str => 
  str === str.split('')
             .reduce((arr, c) => 
               !!~arr.indexOf(c) 
                 ? arr 
                 : arr.concat([c]), [])
             .sort((a, b) => a.localeCompare(b))
             .join('')
const alphabetSubsequence = str => 
  str === [...new Set(str.split('')
                         .sort((a, b) => 
                           a > b 
                             ? 1 
                             : a < b 
                               ? -1 
                               : 0))]
                         .join('')
const alphabetSubsequence = str => 
  str === [...new Set(str.split('')
                         .sort((a, b) => 
                           a.localeCompare(b)
                         )
                     )
          ].join('')
const alphabetSubsequence = str => 
  str === [...new Set(str.split('')
                         .sort((a, b) => 
                           a.charCodeAt(0) - b.charCodeAt(0)
                         )
                     )
          ].join('')

I did learn an interesting thing though. Running this:

"abcdcba".split('').reduce((arr, c) => !!~arr.indexOf(c) ? arr : arr.concat([c]))

Produces the string "abcd". Whereas, runing this:

"abcdcba".split('').reduce((arr, c) => !!~arr.indexOf(c) ? arr : arr.concat([c]), [])

Gives us ["a", "b", "c", "d"]. This shouldn't be surprising really - I'd just forgotten about how indexOf and concat can both work on strings as well as arrays. Neat!

// Using an Object literal:
function getTLD (tld) {
  const tlds = {
    'org': () => 'organization',
    'com': () => 'commercial',
    'net': () => 'network',
    'info': () => 'information',
    'default': () => 'unrecognised',
  };
  return (tlds[tld] || tlds['default'])();
}

// Using a plain Object:
// const tlds = {
//     org: 'organization',
//     com: 'commercial',
//     net: 'network',
//     info: 'information'
// }
// const domainType = ds => ds.map(d => tlds[d.split('.')[d.split('.').length - 1]])

const domainType = ds => ds.map(d => getTLD(d.split('.')[d.split('.').length - 1]))

I was going to go to town and list all the TLDs from here. Then I realsied I'd be doing that most of the day, so I just added a default unrecognised.

Not big nor clever, too tired to be clever today!

const sumOfTwo = (nums1, nums2, value) => {
  for(let i = 0; i < nums1.length; i++){
    for(let j = 0; j < nums2.length; j++){
      if(nums1[i] + nums2[j] === value){
        return true
      }
    }
  }
  return false
}

The coffee kicked in:

const sumOfTwo=(a1,a2,t)=>!!~a1.map(e=>a2.map(a=>a+e)).flat().indexOf(t)

Perforamce wise, there's not much in it.

const extractMatrixColumn = (matrix, column) => matrix.reduce((a, c) => a.concat(c[column]), [])

That was fun! Using the concat thing I mentioned above within a reduce, such a nice way of generating an array from another.

Insomnia meant I saw the original solution via the email... I was going to do something similar so had to re-think things and this is what I came up with:

document.getElementById('btn').setAttribute('disabled', true)
document.getElementById('string').addEventListener('input', ev => {
  const remaining = 140 - ev.target.value.length
  document.getElementById('counterFooter').textContent = remaining + '/140'
  document.getElementById('counterFooter').style.color = ''
  document.getElementById('btn').removeAttribute('disabled')
  remaining < 0 && document.getElementById('btn').setAttribute('disabled', true)
  remaining === 140 && document.getElementById('btn').setAttribute('disabled', true)   
  remaining < 20 && (document.getElementById('counterFooter').style.color = 'red')
})
document.getElementById('btn').addEventListener('click', ev => {
  window.open(`https://twitter.com/intent/tweet?text=${encodeURI(document.getElementById('string').value)}&hashtags=JavaScriptmas&via=DThompsonDev`)
})

I also tweaked the CSS a smidge:

button{
  width:50%;
  background-color: rgb(29, 161, 242);
  border-radius: 10px;
  padding: 0 10%;
}
button h2{
    color: #fff;
}
button:disabled {
   opacity: .5;
   cursor: default;
}

Not a huge change I know, but I do prefer disabling things via an attribute rather than a class - it also means that the click event handler isn't fired on a button with the disabled attribute set; so less code! Oh, I almost forgot, it tweets too, and with the appropriate hashtag and target too! I've gone back to this and changed the keyup to input, helps a smidge, especially for odd times when input is added via the right-click mechanism.

One more to go, yippee!

//EDIT THIS FUNCTION
const spin = async () => {
    //WRITE YOUR CODE HERE
    let counter = 0
    spinningElem.innerHTML = counter
    while(!pushed) {
        await sleep(75) //Paste this wherever you need to sleep the incrimentor 
        counter++
        spinningElem.innerHTML = counter
    }
    stop(counter); //Trigger this function when the STOP button has been pushed 
  
}

//EDIT THIS FUNCTION
function stop(i){
    //WRITE YOUR CODE HERE
    pushed = true
    var result = document.getElementById('result'); //display your result message here
    result.innerHTML = (i === targetInt) ? "Congratulations!" : `Too bad, you were out by ${Math.abs(targetInt - i)}, refresh the page to try again.`
}
const panic = str => `${str.toUpperCase().split(' ').join(' 😱 ')}!`
const transformData = d => d.map(e => ({
  fullName: `${e.name.first} ${e.name.last}`,
  birthday: new Date(e.dob.date).toDateString()
}))
const faveFoods = {
  breakfast: 'croissants',
  lunch: 'pasta',
  supper: 'pizza'
}

const {breakfast, lunch, supper} = faveFoods

document.getElementById('meals').innerHTML = `
For breakfast, I only like ${breakfast}. For lunch, I love ${lunch}, and for supper I want usually want ${supper}.`
const whisper = s => `shh... ${s.endsWith('!') 
  ? s.toLowerCase().slice(0, -1) 
  : s.toLowerCase()}`
const getSaleItems = d => d.filter(e => e.type === "sweet").map(e => ({item: e.item, price: e.price}))
const chunk = (str, size) => {
  const numChunks = Math.ceil(str.length / size)
  const chunks = new Array(numChunks)
  for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
    chunks[i] = str.substr(o, size)
  }
  return chunks
}

const [initialState, instructions] = input.split('\n\n')
const initialStateLines = initialState.split('\n').reverse()
const positions = chunk(initialStateLines.shift(), 4).reduce((a, c) => {
  a[Number(c.trim())] = []
  return a
}, {})

initialStateLines.forEach(line => {
  chunk(line, 4).forEach((position, index) => {
    if (position.trim().length) {
      const { groups: { letter } } = /\s*\[(?<letter>[A-Z])\]\s*/.exec(position)
      positions[Object.keys(positions)[index]].push(letter)
    }
  })
})

/**
 * Part 1
 */
// instructions.split('\n').forEach(instruction => {
//   const {groups: {num, from, to}} = /move (?<num>[0-9]+) from (?<from>[0-9]+) to (?<to>[0-9]+)/.exec(instruction)
//   for(let i = 0; i < Number(num); i++){
//     positions[Number(to)].push(positions[Number(from)].pop())
//   }
// })

/**
 * Part 2
 */
instructions.split('\n').forEach(instruction => {
  const { groups: { num, from, to } } = /move (?<num>[0-9]+) from (?<from>[0-9]+) to (?<to>[0-9]+)/.exec(instruction)
  positions[Number(to)].push(...positions[Number(from)].slice(-Math.abs(Number(num))))
  positions[Number(from)].splice(positions[Number(from)].length - Number(num), Number(num) )
})

console.log(Object.keys(positions).reduce((a, c, i) => {
  return a + positions[c].at(-1)
}, ''))
const range = (start, stop) => Array.from({ length: stop - start + 1 }, (_, i) => start + i)
const contains = (a, b) => a.every(e => b.includes(e)) || b.every(e => a.includes(e))
const overlaps = (a, b) => a.some(e => b.includes(e))

console.log(input.split('\n').reduce((a, line) => {
  const [firstArea, secondArea] = line.split(',').map(elf => range(...elf.split('-').map(e => Number(e))))
  a.contains += contains(firstArea, secondArea) ? 1 : 0
  a.overlaps += overlaps(firstArea, secondArea) ? 1 : 0
  return a
}, {
  contains: 0,
  overlaps: 0
}))
// drop 96 for lowercase
// drop 38 for uppercase

const getCodeValue = letter => letter === letter.toLowerCase()
  ? letter.charCodeAt(0) - 96
  : letter.charCodeAt(0) - 38

const getIntersection = (a, b) => {
  for(let i in a){
    if(b.includes(a[i])){
      return a[i]
    }
  }
}

const getIntersectionThree = (a, b, c) => {
  for(let i in a){
    if(b.includes(a[i]) && c.includes(a[i])){
      return a[i]
    }
  }
}

console.log(input.split('\n').reduce((a, c) => a + getCodeValue(getIntersection(...[c.slice(0, Math.ceil(c.length / 2)).split(''), c.slice(Math.ceil(c.length / 2)).split('')]))
, 0))

let total = 0
const lines = input.split('\n')
for (let i = 0; i < lines.length; i += 3) {
  const chunk = lines.slice(i, i + 3);
  total += getCodeValue(getIntersectionThree(...chunk))
}
console.log(total)

console.log(input.split('\n').reduce((p, _, i, a) => !(i%3)
  ? p + getCodeValue(getIntersectionThree(...a.slice(i, i + 3)))
  : p, 0))
/**
 * Rock:     A, X. Worth: 1. Beats: Scissors
 * Paper:    B, Y. Worth: 2. Beats: Rock
 * Scissors: C, Z. Worth: 3. Beats: Paper
 * 0 if you lost,
 * 3 if the round was a draw
 * and 6 if you won
 */

console.log(input.split('\n').reduce((a, c) => {
  const [them, me] = c.split(' ')
  if(them === 'A'){
    if(me === 'X'){
      a += 3 + 1
    }
    if(me === 'Y'){
      a += 6 + 2
    }
    if(me === 'Z'){
      a += 0 + 3
    }
  }
  if(them === 'B'){
    if(me === 'X'){
      a += 0 + 1
    }
    if(me === 'Y'){
      a += 3 + 2
    }
    if(me === 'Z'){
      a += 6 + 3
    }
  }
  if(them === 'C'){
    if(me === 'X'){
      a += 6 + 1
    }
    if(me === 'Y'){
      a += 0 + 2
    }
    if(me === 'Z'){
      a += 3 + 3
    }
  }
  return a
}, 0))

/**
 * Rock:     A, X. Worth: 1. Beats: Scissors
 * Paper:    B, Y. Worth: 2. Beats: Rock
 * Scissors: C, Z. Worth: 3. Beats: Paper
 * 0 if you lost,
 * 3 if the round was a draw
 * and 6 if you won
 * X: Lose
 * Y: Draw
 * Z: Win
 */

console.log(input.split('\n').reduce((a, c) => {
  const [them, me] = c.split(' ')
  if(them === 'A'){ // They've played Rock
    if(me === 'X'){ // I need to lose
      a += 0 + 3    // I play Scissors
    }
    if(me === 'Y'){ // I need to draw
      a += 3 + 1    // I play Rock
    }
    if(me === 'Z'){ // I need to win
      a += 6 + 2    // I play Paper
    }
  }
  if(them === 'B'){ // They've played Paper
    if(me === 'X'){ // I need to lose
      a += 0 + 1    // I play Rock
    }
    if(me === 'Y'){ // I need to draw
      a += 3 + 2    // I play Paper
    }
    if(me === 'Z'){ // I need to win
      a += 6 + 3    // I play Scissors
    }
  }
  if(them === 'C'){ // They've played Scissors
    if(me === 'X'){ // I need to lose
      a += 0 + 2    // I play Paper  
    }
    if(me === 'Y'){ // I need to draw
      a += 3 + 3    // I play Scissors  
    }
    if(me === 'Z'){ // I need to win
      a += 6 + 1    // I play Rock  
    }
  }
  return a
}, 0))
const elves = input.split('\n\n').map(e => Number(e.split('\n').reduce((a, c) => Number(a) + Number(c))))
console.log(Math.max(...elves))
elves.sort((a, b) => b - a)
console.log(elves.slice(0, 3).reduce((a, c) => a + c))
function createMagicPotion(potions, target) {
  const c = potions.reduce((acc, _, index) => {
    for (let i = index + 1; i < potions.length; i++) {
      if (potions[index] + potions[i] === target) {
        acc.push([index, i]);
      }
    }
    return acc;
  }, []);
  return c[0].length === 1
    ? c[0]
    : c[0].length > 1
      ? c.sort((a, b) => a[1] - b[1])[0]
      : undefined;
}
console.log(createMagicPotion([4, 5, 6, 2], 8));
console.log(createMagicPotion([1, 2, 3, 4], 9));
console.log(createMagicPotion([1, 2, 3, 4], 5));
function battleHorde(zombies, humans) {
  const iteration = Math.max(zombies.length, humans.length);
  const z = zombies.split("").map((e) => Number(e));
  const h = humans.split("").map((e) => Number(e));
  for (let i = 0; i < iteration; i++) {
    if (i + 1 < iteration) {
      console.log(`zombie ${z[i]} vs human ${h[i]}`);
      console.log(`start: humans ${h.join("")}, zombies ${z.join("")}`);
      if (z[i] === h[i]) {
        console.log("tie");
      } else {
        if (z[i] > h[i]) {
          console.log(`zombie wins (${z[i] - h[i]})`);
          z[i + 1] = z[i + 1] + (z[i] - h[i]);
        } else {
          console.log(`human wins (${h[i] - z[i]})`);
          h[i + 1] = h[i + 1] + (h[i] - z[i]);
        }
      }
      console.log(`end: humans ${h.join("")}, zombies ${z.join("")}`);
    } else {
      if (z[i] > h[i]) {
        return `${z[i] - h[i]}z`;
      } else if (z[i] < h[i]) {
        return `${h[i] - z[i]}h`;
      } else {
        return "x";
      }
    }
  }
}
console.log(battleHorde("242", "334"));
console.log(battleHorde("444", "282"));
function findSafestPath(dream) {
  function findPaths(arr, path, i, j, paths) {
    if (i === M - 1 && j === N - 1) {
      path.push(arr[i][j]);
      paths.push(path.reduce((a, c) => a + c, 0));
      path.pop();
      return;
    }
    if (i < 0 || i >= M || j < 0 || j >= N) {
      return;
    }
    path.push(arr[i][j]);
    if (j + 1 < N) {
      findPaths(arr, path, i, j + 1, paths);
    }
    if (i + 1 < M) {
      findPaths(arr, path, i + 1, j, paths);
    }
    path.pop();
  }
  const arr = JSON.parse(JSON.stringify(dream));
  const path = [];
  const paths = [];
  let i = 0,
    j = 0;
  const M = arr.length;
  const N = arr[0].length;
  findPaths(arr, path, i, j, paths);
  return Math.min(...paths);
}
console.log(
  findSafestPath([
    [1, 3, 1],
    [1, 5, 1],
    [4, 2, 1],
  ]),
);
function findTheKiller(whisper, suspects) {
  const regex = new RegExp(
    whisper.substring(whisper.length - 1) === "$"
      ? whisper.replaceAll("~", ".")
      : `${whisper.replaceAll("~", ".")}.*`,
    "i",
  );
  return suspects
    .filter((suspect) => regex.exec(suspect)?.[0] === suspect)
    .join(",");
}
console.log(
  findTheKiller("d~~~~~a", [
    "Dracula",
    "Freddy Krueger",
    "Jason Voorhees",
    "Michael Myers",
  ]),
);
console.log(findTheKiller("~r~dd~", ["Freddy", "Freddier", "Fredderic"]));
console.log(findTheKiller("~r~dd$", ["Freddy", "Freddier", "Fredderic"]));
console.log(findTheKiller("mi~~def", ["Midudev", "Midu", "Madeval"]));
function escapePyramidHead(room) {
  const rows = room.length;
  const cols = room[0].length;

  // Find start (▲) and end (T) positions
  let start, end;
  for (let y = 0; y < rows; y++) {
    for (let x = 0; x < cols; x++) {
      if (room[y][x] === "") {
        start = [x, y];
      } else if (room[y][x] === "T") {
        end = [x, y];
      }
    }
  }

  // If either start or end not found
  if (!start || !end) {
    return -1;
  }

  // Possible moves: up, right, down, left
  const directions = [
    [-1, 0], // left
    [0, 1], // down
    [1, 0], // right
    [0, -1], // up
  ];

  // Helper function to check if a point is valid
  function isValidPoint(row, col) {
    return row >= 0 && row < rows && col >= 0 && col < cols;
  }

  // Initialize visited array and queue for BFS
  const visited = Array(rows)
    .fill()
    .map(() => Array(cols).fill(false));
  const queue = [];

  // Start BFS
  queue.push({ y: start[1], x: start[0], distance: 0 });
  visited[start[1]][start[0]] = true;

  while (queue.length > 0) {
    const current = queue.shift();

    // Check if we reached the end point
    if (current.y === end[1] && current.x === end[0]) {
      return current.distance;
    }

    // Try all possible directions
    for (const [dx, dy] of directions) {
      const newY = current.y + dy;
      const newX = current.x + dx;

      // Check if the new position is valid and not visited
      if (
        isValidPoint(newY, newX) &&
        !visited[newY][newX] &&
        room[newY][newX] !== "#"
      ) {
        visited[newY][newX] = true;
        queue.push({
          y: newY,
          x: newX,
          distance: current.distance + 1,
        });
      }
    }
  }

  // If we get here, no path was found
  return -1;
}

console.log(
  escapePyramidHead([
    [".", ".", "#", ".", ""],
    ["#", ".", "#", ".", "#"],
    [".", ".", ".", ".", "."],
    ["#", "#", "#", ".", "#"],
    ["T", ".", ".", ".", "."],
  ]),
);
console.log(
  escapePyramidHead([
    ["", ".", "#", "."],
    [".", ".", ".", "."],
    ["T", ".", ".", "#"],
    [".", "#", "#", "#"],
  ]),
);
console.log(
  escapePyramidHead([
    ["#", "#", "#"],
    ["", ".", "#"],
    [".", "#", "T"],
  ]),
);