Skip to content

Instantly share code, notes, and snippets.

@haveric
Last active May 12, 2017 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haveric/af6006bb32dff5024eb3f6ab6d40347d to your computer and use it in GitHub Desktop.
Save haveric/af6006bb32dff5024eb3f6ab6d40347d to your computer and use it in GitHub Desktop.
Daily Programmer #313 Hard - Embedded Word List
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
String.prototype.insertAt=function(index, string) {
return this.slice(0, index) + string + this.slice(index);
}
var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
$(document).ready(function() {
//readInput("input/simple.txt", sortInput);
readInput("input/challenge_reduced.txt",sortInput);
});
function readInput(file, callback) {
$.get(file, function(data) {
var split = data.split("\n");
var sorted = new Array();
for (var i = 0; i < split.length; i++) {
var word = split[i].trim();
split[i] = word;
addToSorted(0, word, sorted);
}
callback(split, sorted);
}, "text");
}
function addToSorted(wordIndex, word, sorted) {
var letter = word[wordIndex];
var index = -1;
for (var i = 0; i < sorted.length; i++) {
if (letter === sorted[i].letter) {
index = i;
break;
}
}
if (index === -1) {
index = sorted.length;
sorted.push({letter: letter, children: new Array()});
}
if (wordIndex < word.length) {
sorted[index].children = addToSorted(wordIndex + 1, word, sorted[index].children);
}
return sorted;
}
var parentPartialTree;
function sortInput(data, tree) {
var output = "";
//output = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
parentPartialTree = new Array();
//output = mergeTree(0, tree, parentPartialTree, parentPartialTree, output);
// Merge Tree Result
//output = "actghbodyuriaenlkstmdrphabyoexirftgupnoclvmikjyqaethuowrnlzmaseobticvgudpserhfylmoniktcaewsvbopnruthqildomgajxycokeurnamiclsfzneowgtdaphifvnbleptraiuoxgmceytrnsqdibpchoffkutlaowlmsterpngivckazzldehyvmabdsticomwlouunghipptedrsicablingotilysers";
// Current Merged Best
//output = "actghodyuriaenlstmdrphkabyoexirfgupnclvmijqethuowrnyaseosbticvgzudperhfylmoniktcaewsvbopnrcuthqildmgarjxyoeuzraminclskfeowgtdaphifvnbletraiuoxgmceyrnstlqdibpchofuawmsternglivckazzlpdehyabsuticomvwrlounghipedrscalingtilyses";
// Best previous with a-z
//output = "acdelkihmnopqrswxytuvzabfecghijlnoprstuyabcdefilmnoprstuvxyabchdkjegilmnopqrstuwcbazydefghilmnoprstuvxabcdeghikmnoprstyzcagfljiedmhnoprstuvwyabcdegilnoqrstuwxacdefhiklmoprstihgyabzveoncutradeinopstghmlioszacemteiadlnrtilyces";
// Best Merged after a-z
output = "acdelkihmnopqrswxtuvzabfecghyilnoprstuabcdjefilmnoprstuvxyabchdkegilmnopqrstuwcbazydefghilmnoprstuvxabcdeghikmnoprstyzcagfljiedmhnoprstuvwyabcdegilnoqrstuwxacdefhiklmoprstihgyabzveoncutradeinopstghmlioszacemteriadlntlyces";
// Best of reddit thread
//output = "pscbfgrhkimenovaunltderymwibspchogjuexantfrlzeocidskphquymvatbrlienorsgzcptwhfmylueadrbinosctgexphalrdmkvieyusajongcfetbrpalzwhiquomensdctralytwiongvkzabpfiulesrmedcathnipesotcalxlryusmindtegs";
console.log("Valid: " + testIfValid(0, tree, output));
console.log("Final output: ", output, output.length);
console.time('optimize');
//output = doubleOptimize(tree, output);
console.timeEnd('optimize');
console.log("Initial optimize: ", output, output.length);
output = shiftCount(data, tree, output);
console.log("Valid: " + testIfValid(0, tree, output));
console.log(output, output.length);
}
function mergeTree(lastIndex, tree, originalPartial, currentPartial, output) {
if (tree !== undefined) {
for (var i = 0; i < tree.length; i++) {
var letter = tree[i].letter;
if (letter !== undefined) {
if (!currentPartial[i]) {
currentPartial[i] = new Array();
}
currentPartial[i].letter = letter;
if (!currentPartial[i].children) {
currentPartial[i].children = new Array();
}
var index = output.indexOf(letter, lastIndex);
if (index === -1) {
var diff = 0;
output = output.insertAt(lastIndex, letter);
diff = output.length;
output = optimize(originalPartial, output);
diff = diff - output.length;
index = lastIndex - diff;
}
output = mergeTree(index + 1, tree[i].children, originalPartial, currentPartial[i].children, output)
}
}
}
return output;
}
function testIfValid(lastIndex, tree, total) {
if (tree !== undefined) {
for (var i = 0; i < tree.length; i++) {
var letter = tree[i].letter;
if (letter !== undefined) {
var index = total.indexOf(letter, lastIndex);
if (index === -1 || !testIfValid(index + 1, tree[i].children, total)) {
return false;
}
}
}
}
return true;
}
function testIfValidWord(word, total) {
var length = word.length;
if (length >= total.length) {
return false;
}
var lastIndex = 0;
for (var i = 0; i < length; i++) {
lastIndex = total.indexOf(word[i], lastIndex);
if (lastIndex === -1) {
return false;
}
lastIndex ++;
}
return true;
}
function doubleOptimize(tree, total) {
var o1 = optimize(tree, total);
var o2 = optimizeReverse(tree, total);
if (o1.length <= o2.length) {
total = o1;
} else {
total = o2;
}
console.log("Optimized: " + total.length);
return total;
}
function optimize(tree, total) {
for (var i = 0; i < total.length; i++) {
var removedString = removeAt(total, i);
var valid = testIfValid(0, tree, removedString);
if (valid) {
total = removedString;
i--;
}
}
return total;
}
function optimizeReverse(tree, total) {
for (var i = total.length - 1; i > 0; i--) {
var removedString = removeAt(total, i);
var valid = testIfValid(0, tree, removedString);
if (valid) {
total = removedString;
}
}
return total;
}
function removeAt(word, index) {
return word.slice(0,index) + word.slice(index+1);
}
function reduceEmbedded(data) {
var lastprint = 0;
for (var i = 0; i < data.length; i++) {
var word = data[i];
for (j = 0; j < data.length; j++) {
if (i != j) {
var total = data[j];
var valid = testIfValidWord(word, total);
if (valid) {
data.splice(i,1);
i--;
break;
}
}
}
if (i % 1000 == 0 && i != lastprint) {
console.log("Reduce: ", (i / data.length) * 100);
lastprint = i;
}
}
return data;
}
function reverseString(str) {
return str.split("").reverse().join("");
}
function countUses(data, total) {
var uses = new Array(total.length);
for (var i = 0; i < total.length; i++) {
uses[i] = {index: i, count: 0};
}
for (var i = 0, len = data.length; i < len; i++) {
uses = countUsesWord(data[i], total, uses);
}
return uses;
}
function countUsesWord(word, total, uses) {
var length = word.length;
if (length >= total.length) {
return false;
}
var lastIndex = 0;
for (var i = 0; i < length; i++) {
lastIndex = total.indexOf(word[i], lastIndex);
if (lastIndex > -1) {
uses[lastIndex].count ++;
}
lastIndex ++;
}
return uses;
}
function shiftCount(data, tree, total) {
var uses = countUses(data, total);
for (var i = 0; i < total.length; i++) {
var index = getLowestIndex(uses, i);
var moved = moveLowest(tree, total, index);
if (moved.length < total.length) {
console.log("Moved: ", moved, moved.length);
moved = shiftCount(data, tree, moved);
break;
}
}
for (var i = 0; i < total.length; i++) {
var index = getLowestIndex(uses, i);
var moved = wiggleLowest(tree, total, index);
if (moved.length < total.length) {
console.log("Wiggled: ", moved, moved.length);
moved = shiftCount(data, tree, moved);
break;
}
}
for (var i = 0; i < total.length; i++) {
var index = getLowestIndex(uses, i);
var moved = swapLowest(tree, total, index);
if (moved.length < total.length) {
console.log("Swapped: ", moved, moved.length);
moved = shiftCount(data, tree, moved);
break;
}
}
for (var i = 0; i < total.length; i++) {
var index = getLowestIndex(uses, i);
var moved = moveLowest(tree, total, index, true);
if (moved.length < total.length) {
console.log("Moved: ", moved, moved.length);
moved = shiftCount(data, tree, moved);
break;
}
}
for (var i = 0; i < total.length; i++) {
var index = getLowestIndex(uses, i);
var moved = wiggleLowest(tree, total, index, true);
if (moved.length < total.length) {
console.log("Wiggled: ", moved, moved.length);
moved = shiftCount(data, tree, moved);
break;
}
}
for (var i = 0; i < total.length; i++) {
var index = getLowestIndex(uses, i);
var moved = swapLowest(tree, total, index, true);
if (moved.length < total.length) {
console.log("Swapped: ", moved, moved.length);
moved = shiftCount(data, tree, moved);
break;
}
}
return moved;
}
function moveLowest(tree, total, index, more) {
var original = total;
var lowestLetter = total[index];
var least = 5;
var most = 25;
if (more) {
least = 0;
most = 5;
}
for (var i = most; i > least; i--) {
var rightIndex = index + 1 + i;
var leftIndex = index - i;
if (rightIndex < total.length) {
var temp = total.insertAt(rightIndex, lowestLetter);
temp = optimize(tree, temp);
if (testIfValid(0, tree, temp)) {
if (temp.length < total.length) {
console.log(" Moved R: ", rightIndex, index);
return temp;
}
}
}
if (leftIndex > -1) {
var temp = total.insertAt(leftIndex, lowestLetter);
temp = optimizeReverse(tree, temp);
if (testIfValid(0, tree, temp)) {
if (temp.length < total.length) {
console.log(" Moved L: ", leftIndex, index);
return temp;
}
}
}
}
return original;
}
function wiggleLowest(tree, total, index, more) {
var original = total;
var least = 5;
var most = 25;
if (more) {
least = 0;
most = 5;
}
for (var i = most; i > least; i--) {
var rightIndex = index + 1 + i;
var leftIndex = index - i;
if (rightIndex < total.length) {
var toreorder = original.slice(index, rightIndex);
var beforeReverse = toreorder;
toreorder = reverseString(toreorder);
if (toreorder != beforeReverse) {
var temp = original.slice(0,index) + toreorder + original.slice(index + rightIndex);
if (testIfValid(0, tree, temp)) {
temp = doubleOptimize(tree, temp);
if (temp.length < original.length) {
console.log("R Found wiggle", temp, temp.length);
return temp;
}
}
}
}
if (leftIndex > -1) {
var toreorder = original.slice(leftIndex, index);
var beforeReverse = toreorder;
toreorder = reverseString(toreorder);
if (toreorder != beforeReverse) {
var temp = original.slice(0,leftIndex) + toreorder + original.slice(index + leftIndex);
if (testIfValid(0, tree, temp)) {
temp = doubleOptimize(tree, temp);
if (temp.length < original.length) {
console.log("L Found wiggle", temp, temp.length);
return temp;
}
}
}
}
}
return original;
}
function swapLowest(tree, total, index, more) {
var original = total;
var least = 5;
var most = 25;
if (more) {
least = 1;
most = 5;
}
for (var i = most; i > least; i--) {
var rightIndex = index + 1 + i;
var leftIndex = index - i;
if (rightIndex < total.length) {
var reorder = total.slice(0,rightIndex) + total.slice(rightIndex+Math.floor(i/2), rightIndex + i) + total.slice(rightIndex, rightIndex+Math.floor(i/2)) + total.slice(rightIndex + i);
if (reorder != total && testIfValid(0, tree, reorder)) {
var wiggledString = wiggleLowest(tree, reorder, index, more);
if (wiggledString.length < total.length) {
swapString = wiggledString;
if (swapString != total) {
return swapString;
}
}
}
}
if (leftIndex > -1) {
var reorder = total.slice(0,leftIndex) + total.slice(leftIndex+Math.floor(i/2), leftIndex + i) + total.slice(leftIndex, leftIndex+Math.floor(i/2)) + total.slice(leftIndex + i);
if (reorder != total && testIfValid(0, tree, reorder)) {
var wiggledString = wiggleLowest(tree, reorder, index, more);
if (wiggledString.length < total.length) {
swapString = wiggledString;
if (swapString != total) {
return swapString;
}
}
}
}
}
return original;
}
function getLowestIndex(uses, num) {
uses = uses.sort(function(a, b) { return a.count-b.count;});
return uses[num].index;
}
$(document).ready(function() {
readInput("input/challenge.txt",sortInput);
});
function readInput(file, callback) {
$.get(file + ".txt", function(data) {
var split = data.split("\n");
var reduced = reduceEmbedded(split);
writeFile(file + "_reduced.txt", reduced);
readInput(file, callback);
}, "text");
}
function writeFile(filePath, data) {
console.log("Write file: " + filePath);
var input_string = "";
for (var i = 0; i < data.length; i++) {
input_string += data[i] + "\n";
}
saveFile(filePath, "data:text/plain", new Blob([input_string]));
}
function saveFile (name, type, data) {
if (data != null && navigator.msSaveBlob)
return navigator.msSaveBlob(new Blob([data], { type: type }), name);
var a = $("<a style='display: none;'/>");
var url = window.URL.createObjectURL(new Blob([data], {type: type}));
a.attr("href", url);
a.attr("download", name);
$("body").append(a);
a[0].click();
setTimeout(function(){ // fixes firefox html removal bug
window.URL.revokeObjectURL(url);
a.remove();
}, 500);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment