Last active
January 8, 2016 18:47
-
-
Save FliiFe/9f94467b677a12d2ae97 to your computer and use it in GitHub Desktop.
The Self Descriptive Number. James Grime's/Matt Parker "challenge".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//You can ignore this, this is for the editor. | |
/*jslint node: true */ | |
'use strict'; | |
//Initialize vars | |
var visited = []; | |
var first = '0000000000'; | |
var alternativeMethod = false; | |
var result = first; //Should get to 6210001000 | |
//Main loop. | |
while (!selfDescripting(result)) { | |
first = result; | |
result = correct(first); | |
if (visited.indexOf(result) >= 0 && alternativeMethod) { | |
console.warn("Ooops ! I was stuck in an infinite loop !"); | |
return console.warn("It looks like I'm not good enough yet to find this. Try another length ! Current :", first.length); | |
} else if(visited.indexOf(result) >= 0){ | |
visited = []; | |
alternativeMethod = true; | |
}else { | |
visited.push(first); | |
} | |
//console.log(result); | |
} | |
console.log("Got ya !"); | |
console.log(result); | |
/** | |
* Try to change the String so that most of the values are correct | |
* @param {string} input - string of the number to correct. | |
* @return {boolean} true if number is self-descripting. Otherwise, false. | |
*/ | |
function correct(input) { | |
var output = input.split(''); | |
if (alternativeMethod) { | |
//Litle bit of cheating here. | |
/** | |
* Since 1 is the only digit that can refer to itself only, the "classic" algorithm can't find it. | |
* So we try to force the second digit (index 1) to be one and see if it works. If it doesn't, there | |
* is probably no self-descripting number of the current length. | |
*/ | |
//console.log('Using alt'); | |
output.forEach(function (digit, index) { | |
if(index === 1){ | |
output[index] = 1; | |
return; | |
} | |
output[index] = amountOf(index + '', join(output)); | |
}); | |
return join(output); | |
} else { | |
output.forEach(function (digit, index) { | |
output[index] = amountOf(index + '', join(output)); | |
}); | |
return join(output); | |
} | |
} | |
/** | |
* Cast an array to a String by concatenation. | |
* @param {stringArray} array - Array to join. | |
* @return {string} The concatenated string. | |
*/ | |
function join(array) { | |
var joined = ''; | |
array.forEach(function (digit) { | |
joined += digit; | |
}); | |
return joined; | |
} | |
/** | |
* Tells wether or not a number is self-descripting. | |
* This means first digit is the number of 0 in the number, second the number of 1, ... | |
* @param {string} toCheck - string of the number to check. | |
* @return {boolean} true if number is self-descripting. Otherwise, false. | |
*/ | |
function selfDescripting(toCheck) { | |
var array = toCheck.split(''); | |
var returns = true; | |
array.forEach(function (current, i) { | |
var int = parseInt(current, 10); | |
if (int !== amountOf(i + '', toCheck)) { | |
returns = false; | |
} | |
}); | |
return returns; | |
} | |
/** | |
* Amount of character in a string. | |
* @param {string} char - Char to check for. Can only be 1 length. | |
* @param {string} inString - string to check for char. | |
* @return {number} Amount of char in inString. | |
*/ | |
function amountOf(char, inString) { | |
var amount = 0; | |
for (var i = 0; i < inString.length; ++i) { | |
if (inString[i] === char) { | |
amount++; | |
} | |
} | |
if (amount >= 10) { | |
return 9; | |
} | |
return amount; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment