Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
The Self Descriptive Number. James Grime's/Matt Parker "challenge".
//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