Wednesday, April 26, 2023

Coding Challenge #54 C++ int to std::string (no stringstream or to_string())

Gets a string from an integer (ejemplo gratis: 123 -> "123")

Wanted to come up with my own function for this like 10 years ago but couldn't think of a way and used stringstream. Now after all the binary & bitwise stuff I've been doing, the answer easily popped into my head when the topic of getting the last digit in a number came to mind.

 

 // get lowest digit (of base-10 format number)
int getLowestDigit(int num){
    int lowest_digit = num % 10;
    return lowest_digit;
}

// convert number to string (base-10 representation) in probs a super inefficient way
std::string numToString(int num){
    std::string str = "";
    while(num > 0){
        int digi = num % 10; // current right-most digit
        str += '0' + digi;
        num /= 10; // move number over by one base-10 digit's worth
    }
    
    // above number string is backwards. flip it
    std::string fin = "";
    for(int xint = fin.length() - 1;xint > -1;xint--){
        fin += str[xint];
    }
    
    return fin;
}

Sunday, April 16, 2023

Coding Challenge #53 Combinations

 // the math formula (in my dialect): x = n! / ((n-r)!r!)

// finds factorial of a number
function fac(x){
    var done = x;
    while(x > 1) done *= --x;
    return done;
}

// finds combinations given n = total number of options, and r = slots available to be filled with options.
function combo(n, r){
    return fac(n) / (fac(n-r) * fac(r));
}

console.log("Combinations for 3 elected positions, with 6 candidates = " + combo(6, 3));

Saturday, April 15, 2023

Coding Challenge #52 Factorial (Recursive)

 // a recursive version of a function to find a factorial of a number
// a factorial of a number being the product of that number multiplied by all numbers between itself and 1 (e.g. 3! = 3 * 2 * 1. 4! = 4 * 3 * 2 * 1.)
function fac_rec(x){
    if(x <= 1) return 1;
    else return x * fac_rec(x-1);
}

Friday, April 14, 2023

Coding Challenge #51 Factorial (Loop)

 // finds factorial of a number
function fac(x){
    var done = x;
    while(x > 1) done *= --x;
    return done;
}

Thursday, April 13, 2023

Coding Challenge #50 Permutations

 // a function to calculate the permutations given total possibilities and events to calculate for.
// for example, in a race, if we want to know total possible permutations for who comes in 1rst & 2nd, and we have 4 racers, then that'd be cp(4,2) = 12
// in order for the result to be accurate and meaningful, the eventsToCalcFor must be <= totalPossibilities
function cp(totalPossibilities, eventsToCalcFor){
    var fin = totalPossibilities;
    for(var xint = 1;xint < eventsToCalcFor;xint++){
        fin *= totalPossibilities-xint;
    }
    return fin;
}

console.log("24 racers can come into 1rst, 2nd, and 3rd places how many different ways? Answer: " + cp(24, 3));

console.log("I can organize my green, blue, and orange socks how many different ways? Answer: " + cp(3, 3));

Wednesday, April 12, 2023

Coding Challenge #49 Number Predicter - Version 3

 /* version 3
Again slightly more useful & accurate than version 2 in that this version will try a little harder for when the supplied time is between the min & max.
I noticed in version 2 that f(1993.5) returned < than f(1993). Odd. This version, when supplied 1993.5, will grab values for the closest surrounding dataset values (1993 & 1994) and interpolate linearly between those two specifically.
*/

/* version 3 notes (on getting the between the indices)
4.5 // input time to predict
4, 7 // range times
100, 150 // range values
7-4 = 3 // time diff
150 - 100 = 50 // value diff
50/3 = 16.6xxxx // per value value

100 + ((4.5 - 4) * 16.6xxxx)
minV + ((input - minT) * perYear)
*/

var data = [{year:1992,cost:1440},
{year:1993,cost:1560},
{year:1994,cost:1620},
{year:1995,cost:1780},
{year:1996,cost:1860},
{year:1997,cost:1920},
{year:1998,cost:1940},
{year:1999,cost:1999},
{year:2000,cost:2040}];
var data2 = [];
for(var xint = 0;xint < 10;xint++)
    data2.push({year:2000+xint,pay:10+(xint/10)});
// then do one for #pets compared to #renkou ppl in household

// data is the cost of a used car with x miles on it in a certain year; goal: given a year, predict the cost that year
// data2 is hourly pay each year starting 2000 $10.00/hr. Goal: given a year, predict the pay that year


// assumes array is sorted least to greatest
function getNearIdxs(ary, val){ // returns object with 2 valid indices (assuming ary was not empty)
    if(ary.length < 2) return {min:0,max:0};
    var out = {min:0,max:0};
    for(var xint = 0,len=ary.length;xint < len;xint++){
        if(val < ary[xint]){
            out.max = xint;
            out.min = Math.max(0,xint-1);
            return out;
        }
    }
    return out;
}

// where timeName is the variable per object with the time value (the consistent change over time)
// and valueName is the value we're trying to find given a time
// .predict(v): returns a predicted linear output
// Note: 2 same .times[] values (like year 1993, 1993, 1994) would confuse it and produce probably undesirable output
function reader(data, timeName, valueName){
    this.times = [];
    this.values = [];
    this.minT = 1; // minimum time
    this.maxT = 1;
    this.minV = 1; // minimum value
    this.maxV = 1;
    this.diffT = 1;
    this.diffV = 1;
    this.perYear = 1; // final linear quotient
    
    // sort the data so we can easily grab the closest values by indices (least to greatest)
    data.sort((a,b,tname)=>{return a[tname]>b[tname];});
    this.d = data;
    
    // now let's try to make a mini model
    this.minT = data[0][timeName];
    this.maxT = data[0][timeName];
    this.minV = data[0][valueName];
    this.maxV = data[0][valueName];
    for(var xint = 0;xint < data.length;xint++){
        this.minT = Math.min(this.minT, data[xint][timeName]);
        this.maxT = Math.max(this.maxT, data[xint][timeName]);
        this.minV = Math.min(this.minV, data[xint][valueName]);
        this.maxV = Math.max(this.maxV, data[xint][valueName]);
        this.times.push(data[xint][timeName]);
        this.values.push(data[xint][valueName]);
    }
    this.diffT = Math.max(1,this.maxT - this.minT);
    this.diffV = Math.max(1,this.maxV - this.minV);
    this.perYear = this.diffV / this.diffT; // cost per year linear avg
    
    this.predict = function(time){
        if(time > this.maxT){
            return this.maxV + ((time-this.maxT) * this.perYear);
        }else if(time < this.minT){
            return this.minV - ((this.minT-time) * this.perYear);
        }else{ // within range
            var found = false;
            var val = 0;
            for(var xint = 0;xint < this.times.length;xint++){
                if(this.times[xint] == time){
                    found = true;
                    val = this.values[xint];
                    break;
                }
            }
            if(found){
                return val; // found in defined dataset
            }else{
                // estimate
                var x = getNearIdxs(this.times, time);
                var diffT = this.times[x.max] - this.times[x.min];
                var diffV = this.values[x.max] - this.values[x.min];
                if(diffT == 0) diffT = 1;
                var vPerT = diffV / diffT;
                return this.values[x.min] + ((time - this.times[x.min]) * vPerT);
            }
        }
    }
}

var r1 = new reader(data, 'year', 'cost');
console.log(r1.predict(1992));
console.log(r1.predict(1993));
console.log(r1.predict(1994));
console.log(r1.predict(1993.5));
console.log(r1.predict(1993.1));
console.log(r1.predict(1993.9));

var r2 = new reader(data2, 'year', 'pay');
console.log(r2.predict(2001));

Tuesday, April 11, 2023

Coding Challenge #48

submitted for Coursera quiz. Read int's from a file, and calculate their average

#include <stdio.h>
int main(){
    FILE *filePointer; // this is the pointer to the file
    int buffer[1000]; // file content
    int safety = 10000;
    int count = 0;
    filePointer = fopen("file.tsv", "r"); // open the file with file pointer to the file
    while(fscan(filePointer, "%d\t", &buffer[count]) && --safety){
        count++;
    } // read the file the file pointer file
    fclose(filePointer); // close the file pointer to the file
    int total = 0; // total the weight
    for(int xint = 0;xint<count;xint++)total+=buffer[xint]; // it make the total the total to make the average
    int average=total/count;
    printf("average:%d",count);
}

Monday, April 10, 2023

Coding Challenge #47 Get Surrounding Indices (Accepts Floats)

 // assumes array is sorted least to greatest
function getNearIdxs(ary, val){ // returns object with 2 valid indices (assuming ary was not empty)
    if(ary.length < 2) return {min:0,max:0};
    var out = {min:0,max:0};
    for(var xint = 0,len=ary.length;xint < len;xint++){
        if(val < ary[xint]){
            out.max = xint;
            out.min = Math.max(0,xint-1);
            return out;
        }
    }
    return out;
}

var a = [1,2,3,4,5,6,7,8];
function test(val){
    x = getNearIdxs(a, val);
    console.log("Min: " + a[x.min] + ", max: " + a[x.max]);
}

test(2); // should return min 2, max 3
test(4); // 4, 5
test(4.5); // 4, 5
test(6.9); // 6, 7

Sunday, April 9, 2023

Coding Challenge #46 Number Predicter - Version 2

 /* version 2
Slightly more useful for unimportant guesstimations.
This version is able to retrieve the data found in the dataset if the user predict()s a value that happens to be there.
Otherwise, it will assume similar to version 1 but more satisfactorily: getting it from 3 scopes: greater than the defined range, less than the defined range, and within the defined range.
*/

/* ideas it's based off it
2004 - 2010 // time range
100 - 400 // value range
300/6 = 50
2011 => 450

diff1 = max1-min1 // time
diff2 = max2-min2 // val
linearYear = diff1 / diff2

f(time)
 |
 V
(time > max1)
    max2 + ((time-max1) * linearYear)
(time < min1)
    min2 - ((min1-time) * linearYear)
else
    x = binarySearchFor(time)
    if x == null
        // value not in defined dataset, interpolate linearly from minimum
        min2 + ((time-min1) * linearYear)
    else
        return x // actually found value in defined dataset
*/

var data = [{year:1992,cost:1440},
{year:1993,cost:1560},
{year:1994,cost:1620},
{year:1995,cost:1780},
{year:1996,cost:1860},
{year:1997,cost:1920},
{year:1998,cost:1940},
{year:1999,cost:1999},
{year:2000,cost:2040}];
var data2 = [];
for(var xint = 0;xint < 10;xint++)
    data2.push({year:2000+xint,pay:10+(xint/10)});
// then do one for #pets compared to #renkou ppl in household

// data is the cost of a used car with x miles on it in a certain year; goal: given a year, predict the cost that year
// data2 is hourly pay each year starting 2000 $10.00/hr. Goal: given a year, predict the pay that year

// where timeName is the variable per object with the time value (the consistent change over time)
// and valueName is the value we're trying to find given a time
// .predict(v): returns a predicted linear output
function reader(data, timeName, valueName){
    this.times = [];
    this.values = [];
    this.minT = 1; // minimum time
    this.maxT = 1;
    this.minV = 1; // minimum value
    this.maxV = 1;
    this.diffT = 1;
    this.diffV = 1;
    this.perYear = 1; // final linear quotient
    
    // now let's try to make a mini model
    this.minT = data[0][timeName];
    this.maxT = data[0][timeName];
    this.minV = data[0][valueName];
    this.maxV = data[0][valueName];
    for(var xint = 0;xint < data.length;xint++){
        this.minT = Math.min(this.minT, data[xint][timeName]);
        this.maxT = Math.max(this.maxT, data[xint][timeName]);
        this.minV = Math.min(this.minV, data[xint][valueName]);
        this.maxV = Math.max(this.maxV, data[xint][valueName]);
        this.times.push(data[xint][timeName]);
        this.values.push(data[xint][valueName]);
    }
    this.diffT = Math.max(1,this.maxT - this.minT);
    this.diffV = Math.max(1,this.maxV - this.minV);
    this.perYear = this.diffV / this.diffT; // cost per year linear avg
    
    this.predict = function(time){
        if(time > this.maxT){
            return this.maxV + ((time-this.maxT) * this.perYear);
        }else if(time < this.minT){
            return this.minV - ((this.minT-time) * this.perYear);
        }else{ // within range
            var found = false;
            var val = 0;
            for(var xint = 0;xint < this.times.length;xint++){
                if(this.times[xint] == time){
                    found = true;
                    val = this.values[xint];
                    break;
                }
            }
            if(found){
                return val; // found in defined dataset
            }else{
                return this.minV + ((time-this.minT) * this.perYear); // estimate
            }
        }
    }
}

var r1 = new reader(data, 'year', 'cost');
console.log(r1.predict(1992));

var r2 = new reader(data2, 'year', 'pay');
console.log(r2.predict(2001));

Saturday, April 8, 2023

Coding Challenge #45 Number Predicter - Version 1

 /* version 1
Simplest version, creates a value per the year and predict() returns that value * the year.
Comically inaccurate, can't even properly return values found in the dataset handed to it.
*/

var data = [{year:1992,cost:1440},
{year:1993,cost:1560},
{year:1994,cost:1620},
{year:1995,cost:1780},
{year:1996,cost:1860},
{year:1997,cost:1920},
{year:1998,cost:1940},
{year:1999,cost:1999},
{year:2000,cost:2040}];
var data2 = [];
for(var xint = 0;xint < 10;xint++)
    data2.push({year:2000+xint,pay:10+(xint/10)});
// then do one for #pets compared to #renkou ppl in household

// data is the cost of a used car with x miles on it in a certain year; goal: given a year, predict the cost that year
// data2 is hourly pay each year starting 2000 $10.00/hr. Goal: given a year, predict the pay that year

// where timeName is the variable per object with the time value (the consistent change over time)
// and valueName is the value we're trying to find given a time
// .predict(v): returns a predicted linear output
function reader(data, timeName, valueName){
    this.d = data;
    this.min = 0; // minimum
    this.max = this.min;
    this.avgVal = 0;
    this.avgTime = 0;
    this.perYear = 0; // final linear quotient
    
    // now let's try to make a mini model using simple proportionalism
    var totalVal = 0;
    var totalYear = 0;
    this.min = data[0][timeName];
    for(var xint = 0;xint < data.length;xint++){
        totalVal += data[xint][valueName];
        totalYear += data[xint][timeName];
        this.min = Math.min(this.min, data[xint][timeName]);
        this.max = Math.max(this.max, data[xint][timeName]);
    }
    this.avgVal = data.length > 0 ? totalVal / data.length : 1;
    this.avgTime = data.length > 0 ? totalYear / data.length : 1;
    this.perYear = this.avgVal / this.min;
    
    this.predict = function(time){
        return time * this.perYear;
    }
}

var r1 = new reader(data, 'year', 'cost');
console.log(r1.predict(1992));

var r2 = new reader(data2, 'year', 'pay');
console.log(r2.predict(2001));

Friday, April 7, 2023

Coding Challenge #44 2-Dimensional Inventory

 /*
Briefcase Inventory
Logic demo of 2d spatial inventory (vector-based).
I think. might be abusing those words.
Same kind of inventory famously used in Resident Evil 4 and Cabal Online.
The user must manage the inventory slots efficiently by rotating and moving the items.
The inventory is defined as an X-by-Y box with X*Y slots (asserting that X>1&&Y>1).
The user can pick up an item from the case, hold an item above the case, and place the held item down (which would swap it with a single item below it).
There are some assumptions for this script's use case; they are noted in comments throughout the script. (Search "assum")
*/

// rough draft & pseudocode:
/*inv manager re4
    basically the item works with dots
    on A press:
        if each dot this item takes in this rotation == null
            place item
        else if all dots belong to 1 item
            swap item for the 1 item under it
        else (dots belong to more than 1 object)
            error sound, can't place held item
board []
board[x].itemIndex
if board[ heldItem.dots[xint].x + heldItem.offsetX + ((heldItem.dots[xint].y + heldItem.offsetY) * briefcaseWidth) ].itemIndex == 0
    # where itemIndex of 0 signifies a vacant slot in the briefcase
    changed my mind; -1 is empty, max is 127 (s8)
*/

// we make the assumption that an item that can be held and attempted to be placed in the briefcase is actually small enough to fit into an empty briefcase (example if our game briefcase is 4x4, we don't have any 5x4 items, which would be too long to fit into the briefcase even when empty)

function item(dots){
    this.rotation = 0; // current rotation. 0=upright.1=90*clockwise.2=180*(upside down).3=270*.
    this.dots = []; // array of indices from coords (x,y)
    this.width = 0;
    this.height = 0;
    this.stringBlueprint = "";
    this.fromString = function(s){
        this.stringBlueprint = s;
        var d = [];
        var line = 0; // which row (y-axis)
        var width = s.indexOf('\n'); // we assume the string is properly structured
        this.width = width;
        var xprog = 0; // which column (x-axis)
        if(width == -1) width = s.length;
        for(var xint = 0;xint < s.length;xint++){
            if(s.charAt(xint) == 'o'){
                d.push(xprog + (line * width));
                xprog++;
            }else if(s.charAt(xint) == '\n'){
                line++;
                xprog = 0;
            }
        }
        this.height = line + 1;
        this.dots = d;
    }
    this.toString = function(){ // dots to string, really just returned stored string
        if(this.rotation == 0) return this.stringBlueprint;
        var block = [];
        for(var xint = 0, len = this.width * this.height;xint < len;xint++) block[xint] = "x";
        for(var xint = 0;xint < this.dots.length;xint++) block[this.dots[xint]] = "o";
        var out = "";
        for(var yint = 0;yint < this.height;yint++){
            for(var xint = 0;xint < this.width;xint++) out += block[xint + (this.width * yint)];
            out += "\n";
        }
        return out;
    }
    this.rotateClockwise = function(){
        this.rotation++;
        if(this.rotation >= 4) this.rotation = 0;
        var oldWidth = this.width;
        var oldHeight = this.height;
        var newWidth = oldHeight;
        var newHeight = oldWidth;
        var res = [];
        for(var xint = 0;xint < this.dots.length;xint++){
            //console.log("roclo[" + xint + "]: " + this.dots[xint]);
            var oldx = this.dots[xint] % oldWidth;
            var oldy = Math.floor(this.dots[xint] / oldWidth);
            var newy = oldx;
            var newx = (newHeight-1) - oldy;
            res.push(newx + (newy * newHeight)); // save translated dot as index
            //console.log("old x/y ",oldx,",",oldy," -> new x/y ",newx,",",newy,". logged idx: " + res[res.length-1]);
        }
        this.dots = res;
        this.width = newWidth;
        this.height = newHeight;
    }
    this.rotateCounterClockwise = function(){
        this.rotation--;
        if(this.rotation < 0) this.rotation = 3;
        var oldWidth = this.width;
        var oldHeight = this.height;
        var newWidth = oldHeight;
        var newHeight = oldWidth;
        var res = [];
        for(var xint = 0;xint < this.dots.length;xint++){
            console.log("roclo[" + xint + "]: " + this.dots[xint]);
            var oldx = this.dots[xint] % oldWidth;
            var oldy = Math.floor(this.dots[xint] / oldWidth);
            var newx = oldy;
            var newy = (newWidth-1) - oldx;
            res.push(newx + (newy * newHeight)); // save translated dot as index
            //console.log("old x/y ",oldx,",",oldy," -> new x/y ",newx,",",newy,". logged idx: " + res[res.length-1]);
        }
        this.dots = res;
        this.width = newWidth;
        this.height = newHeight;
    }
    if(typeof dots == "string"){ // construct from string
        this.fromString(dots);
    }
}
function makeBriefcase(width, height){
    briefcase = [];
    briefcaseWidth = width;
    briefcaseHeight = height;
    for(var xint = 0;xint < width;xint++){
        for(var yint=0;yint<height;yint++) briefcase.push(-1);
    }
    briefcaseLen = (width * height) - 1; // assumes width & height are not both 1
}
function makeItem(name, dots){ // add an item to the shop
    shopNames.push(name);
    shop.push(new item(dots));
    console.log("\n=====\nshop got new stock: " + name + "\n" + dots + "\n=====");
}
function ctoi(x,y){ // coordinates to index
    return x + (y * briefcaseHeight);
}
function cloneItem(original){
    var copy = new item();
    copy.rotation = original.rotation;
    copy.width = original.width;
    copy.height = original.height;
    copy.dots = [];
    for(var xint = 0, len = original.dots.length;xint < len;xint++) copy.dots.push(original.dots[xint]);
    copy.stringBlueprint = original.stringBlueprint;
    return copy;
    // i guess coulda also just used below instead of all above (but above is probably a little faster than additionally parsing the string):
    // return new item(original.stringBlueprint);
}

var briefcase = []; // where our owned items are stored. manage this space. array of s8's. represents indices of the inventory.
var briefcaseWidth = 4;
var briefcaseHeight = 4;
var briefcaseLen = 15; // max index + 1
var shop = []; // items to select to add to inv. also acts as a database for item definitions here
var shopNames = []; // item names
var inventory = []; for(var xint=0;xint<8;xint++)inventory[xint]=-1;// a list of our owned items. indices of shop; list of item IDs. -1 = empty inventory slot. needs to be static length for briefcase values.
var holdingItem = false;
var itemInHands = null;
function tryToPlace(heldItem, x, y){
    // we assume that the item will not be out of bounds over the briefcase
    // for example, an item of width 3 cannot be placed at index 1 in a briefcase of width 3, because the right-most dot would be outside the suitcase, causing an exception here
    var matchedAny = false;
    var matchedID = -1;
    for(var xint = 0, len = heldItem.dots.length;xint < len;xint++){
        var slot = briefcase[ctoi(x,y) + heldItem.dots[xint]]; // an underlying slot(dot) in the briefcase
        if(slot != -1){ // overlapped non-empty slot
            if(matchedAny){
                if(matchedID == slot) continue; // it's ok, same item we already matched
                else{
                    // 2nd item that our held item is overlapping
                    // we can't place the item because we can't be holding both briefcase items - we can only hold 1 item at a time
                    // can play an ERRRRH sound here :)
                    return;
                }
            }else{
                // first tim overlapping, note the ID of the item in the briefcase that is overlapping (we can only carry 1 item in our hands)
                matchedAny = true;
                matchedID = slot;
            }
        }
    }
    
    // check there is space in the inventory to store the item we are holding
    // this may be unnecessary, as in most cases there would be a number of inventory slots equal to the 'dots'
    // e.g. a 4x4 case has 4*4 slots (16), so 16 1x1 items could be fit into it
    // therefore this check is a formality
    var intoInvSlot = -1;
    if(!matchedAny){ // only need to check if we're not swapping for an item in inv
        var found = false;
        for(var xint = 0;xint < inventory.length;xint++){
            if(inventory[xint] == -1){
                found = true;
                intoInvSlot = xint;
                break;
            }
        }
        if(!found){
            // can play error sound here and show message "Max number of items in briefcase reached!"
            // This is the case where there is an arbitrary limit of inv items regardless of case slots
            // e.g. 4x4 case size (16 slots) but player can only have 3 items in the case at any time, regardless of item size
            return;
        }
    }
    
    // save the inventory item from briefcase in case we need to swap it
    var itemFromBriefcase;
    if(matchedAny){
        // is there space in the inventory to hold the briefcase item?
        //itemFromBriefcase = inventory.splice(id,1)[0]; // move item from inventory (briefcase) to temporary spot
        itemFromBriefcase = inventory[id];
        intoInvSlot = id;
    }
    
    // let's now set the held item down
    inventory[intoInvSlot] = itemInHands;
    // update briefcase dots where the previously held item was set down so that they point to this inventory slot
    for(var xint = 0;xint < itemInHands.dots.length;xint++){
        // we have to change the dot value: y for the dot (with width of the item) is not necessarily the same as y for the briefcase, due to a difference in width.
        // example without change: pistol into 4x4 briefcase. briefcase is then [0,0,0,-1,.....]
        // example WITH change: pistol into 4x4 briefcase. briefcase becomes [0,0,-1,-1,0,-1,-1,-1....]
        // might help to make illustration
        /*
        no change, using raw value from heldItem.dots[xint]
        ooox
        xxxx
        (the width of the item is 2)
        (the briefcase is 4x2)
        See the issue? The item doesn't wrap because the width doesn't match the briefcase
        
        fixed width to match briefcase
        ooxx
        oxxx
        (width of item: 2)
        (briefcase is 4x2)
        Notice the difference? The handle of the pistol (bottom 'o') is now properly wrapped to the below line like it's supposed to be, because it used the offset of the briefcase's width for each line.
        */
        // so here are the
        var ix = heldItem.dots[xint] % heldItem.width;
        var iy = Math.floor(heldItem.dots[xint] / heldItem.width);
        briefcase[ctoi(x,y) + ctoi(ix,iy)] = intoInvSlot; // payload being equivalent to ctoi(x+ix,y+iy)
        // briefcase[ctoi(x,y) + heldItem.dots[xint]] = intoInvSlot; // original, erroneous line that didn't respect briefcase width
    }
    
    if(matchedAny){
        // we have to replace the held item with the item we overlapped
        itemInhands = itemFromBriefcase; // now we're holding the item we replaced
    }
    else holdingItem = false; // we set it down into empty slots. we're not holding anything now. (don't need to nullify itemInHands)
}
function pickUp(x, y){ // not holding item, pick up item in briefcase at coords
    var id = briefcase[ctoi(x,y)];
    // -1 means empty briefcase slot
    if(id >= 0){
        holdingItem = true;
        itemInHands = shop[inventory[id]];
        // remove item from briefcase, we are now holding it
        for(var xint = 0;xint < briefcaseLen;xint++){
            if(briefcase[xint] == id) briefcase[xint] = -1;
        }
    }
}
function trashHeldItem(){
    holdingItem = false;
}
function buyItem(shopIndex){ // convenient function to copy a shop item into itemInHands
    if(holdingItem) trashHeldItem();
    itemInHands = cloneItem(shop[shopIndex]);
    holdingItem = true;
}
function pressSpace(){ // function that acts as the button to pick up / place items in briefcase.
    if(holdingItem) tryToPlace(itemInHands);
    else pickUp(x,y);
}
function pressX(){ // used to trash a held item
    if(holdingItem) trashHeldItem();
}

makeBriefcase(4,4); // briefcase has 16 slots: width of 4, height of 4
makeItem("pistol", "oo\nox"); // L shape
makeItem("RPG", "ooooo\nxoxxx"); // vertical bar with a handle on 2nd column of 2nd row

shop[0].toString();
shop[0].rotateClockwise();
shop[0].rotateClockwise();
shop[0].rotateCounterClockwise();
console.log("now 90* clockwise");
shop[0].toString();

itemInHands = cloneItem(shop[0]);
console.log("in hands: ");
itemInHands.toString();

console.log('placing... @ 0,0 in briefcase');
tryToPlace(cloneItem(itemInHands), 0,0);
console.log("Briefcase now: ", briefcase);

Thursday, April 6, 2023

Coding Challenge #43 String of Crimes

An exercise in recursive objective propagation in a functional paradigm. Really just for some fun in a simulator-type virtual city.

/*crime tree
    each crime can have several others (given a simple crime, we can do other crimes, as long as the victim is alive or the assailant is willing)
    like: criminal X wants to rob someone. this may lead to other crimes like (defendant Y fights back) battery, 2nd degree murder, disposing of a corpse
    */
    
var crimes = ["rob", "beat", "kill", "insult", "dismembered", "poison", "threaten", "pee on"];
var maxCrimesPerString = 10;
function crime(w, target, cnt){
    this.name = w;
    this.next = null;
    if(cnt < maxCrimesPerString && Math.round(Math.random() * 1) == 0){ // 50% chance, while under limit
        var idx = Math.round(Math.random()*(target.dos.length-1));
        var t = target.dos[idx];
        if(t != "beat" && t != "insult") target.dos.splice(idx,1); // can't do some crimes more than once
        if(t == "beat" && target.health > 0){ // if beat, decrease HP.
            target.health = Math.max(0, target.health - 20);
            if(target.health == 0){ // if beat to death, can't "kill" later
                for(var zint = 0, len = target.dos.length;zint < len;zint++){
                    if(target.dos[zint] == "kill"){
                        target.dos.splice(zint,1);
                        break;
                    }
                }
            }
        }else if(t == "kill") target.health = 0;
        this.next = new crime(t, target, cnt+1);
    }
    this.toString = function(){
        if(this.next != null) return this.name + ", " + this.next.toString();
        else return this.name;
    }
}
function victim(name){
    this.name = name;
    this.health = 100;
    this.dos = []; // things that can be done to victim
    for(var xint = 0;xint < crimes.length;xint++)
        //this.status[crimes[xint]] = false;
        this.dos.push(crimes[xint]);
}


x = new crime("rob", new victim("John Doe"), 1);
console.log(x.toString());

Wednesday, April 5, 2023

Coding Challenge #42 Personality Quiz

Naruto Personality Quiz

Which Naruto Character Are You?

Tuesday, April 4, 2023

Coding Challenge #41 MGSV Sort New Recruits

// Inspired by MGSV. The base has several stats and soldiers also have the same several stats. When the base is full of high-stat soldiers, the base has high stats in reflection.
// The player can recruit soldiers, and those new recruits are automatically sorted by the system as to where they should go -- we will do that sorting.
// When a new recruit is added, their highest stat determines where in the base they will be stationed.
// If a new recruit doesn't increase the base stats at all (e.g. base has all max stat soldiers) then the new recruit is dismissed without being stationed at the base.

// for this test, the stats will be atk (attack/offensive), def (defense), and med (medical knowledge & skill)
function base(atk, def, med){
    this.atk = atk;
    this.def = def;
    this.med = med;
    this.soldiersAtk = []; // soldiers for each station ATK, DEF, and MED
    this.soldiersDef = [];
    this.soldiersMed = [];
    this.soldiersMax = 2; // max soldiers per category
    this.calc = function(){ // calculate total base atk,def,med as the sum of its soldiers'
        var total = 0;
        for(var xint = 0, len = this.soldiersAtk.length;xint < len;xint++) total += this.soldiersAtk[xint].atk;
        this.atk = total;
        total = 0;
        for(var xint = 0, len = this.soldiersDef.length;xint < len;xint++) total += this.soldiersDef[xint].def;
        this.def = total;
        total = 0;
        for(var xint = 0, len = this.soldiersMed.length;xint < len;xint++) total += this.soldiersMed[xint].med;
        this.med = total;
    }
}
function soldier(atk, def, med){
    this.atk = atk;
    this.def = def;
    this.med = med;
}

function sortSoldiers(base, soldiers){ // obj base, ary of objs soldiers
    for(var xint = 0, len = soldiers.length;xint < len;xint++){
        if(Math.max(soldiers[xint].atk,soldiers[xint].def,soldiers[xint].med) == soldiers[xint].atk){ // atk is his highest (or one of highest equally) stats
            //console.log('soldier ' + xint + ' is atk. soldier: ',soldiers[xint]);
            if(base.soldiersAtk.length < base.soldiersMax){ // add the soldier
                base.soldiersAtk.push(soldiers.splice(0,1)[0]);
                xint--;
                len--;
                continue; // added. next soldier
            }else{ // replace weakest soldier in the category
                var rep = 0; // index of base soldier being replaced
                var lowest = base.soldiersAtk[0].atk;
                for(var yint = 0, ylen = base.soldiersAtk.length;yint < ylen;yint++){
                    if(base.soldiersAtk[yint].atk < lowest){
                        rep = yint;
                        lowest = base.soldiersAtk[yint].atk;
                        break;
                    }
                }
                if(soldiers[xint].atk > lowest){
                    soldiers.push(base.soldiersAtk[rep]); // remove old soldier from base
                    base.soldiersAtk[rep] = soldiers.splice(0,1)[0]; // move new soldier to base
                    xint--;
                    continue; // added; next soldier
                }
            }
        }
        // by here, the soldier's best stat wasn't ATK or there wasn't room for another ATK soldier and the soldier didn't improve the overall ATK
        if(Math.max(soldiers[xint].atk,soldiers[xint].def,soldiers[xint].med) == soldiers[xint].def){
            //console.log('soldier ' + xint + ' is def. soldier: ',soldiers[xint]);
            if(base.soldiersDef.length < base.soldiersMax){ // add the soldier
                base.soldiersDef.push(soldiers.splice(0,1)[0]);
                xint--;
                len--;
                continue; // added. next soldier
            }else{ // replace a soldier
                var rep = 0; // index of base soldier being replaced
                var lowest = base.soldiersDef[0].def;
                for(var yint = 0, ylen = base.soldiersDef.length;yint < ylen;yint++){
                    if(base.soldiersDef[yint].def < lowest){
                        rep = yint;
                        lowest = base.soldiersDef[yint].def;
                        break;
                    }
                }
                if(soldiers[xint].def > lowest){
                    soldiers.push(base.soldiersDef[rep]); // remove old soldier from base
                    base.soldiersDef[rep] = soldiers.splice(0,1)[0]; // move new soldier to base
                    xint--;
                    continue; // added; next soldier
                }
            }
        }
        if(Math.max(soldiers[xint].atk,soldiers[xint].def,soldiers[xint].med) == soldiers[xint].med){
            //console.log('soldier ' + xint + ' is med. soldier: ',soldiers[xint]);
            if(base.soldiersMed.length < base.soldiersMax){ // add the soldier
                base.soldiersMed.push(soldiers.splice(0,1)[0]);
                xint--;
                len--;
                continue; // added. next soldier
            }else{ // replace a soldier
                var rep = 0; // index of base soldier being replaced
                var lowest = base.soldiersMed[0].med;
                for(var yint = 0, ylen = base.soldiersMed.length;yint < ylen;yint++){
                    if(base.soldiersMed[yint].med < lowest){
                        rep = yint;
                        lowest = base.soldiersMed[yint].med;
                        break;
                    }
                }
                if(soldiers[xint].med > lowest){
                    soldiers.push(base.soldiersMed[rep]); // remove old soldier from base
                    base.soldiersMed[rep] = soldiers.splice(0,1)[0]; // move new soldier to base
                    xint--;
                    continue; // added; next soldier
                }
            }
        }
    }
    base.calc();
}

function test(base, soldiers){
    
    console.log("Sorting " + soldiers.length + " soldiers into the base.");
    sortSoldiers(base, soldiers);
    console.log("Base stats now: " + base.atk + " ATK, " + base.def + " DEF, " + base.med + " MED.\nBase soldiers: ATK: ",base.soldiersAtk.length,". DEF: ",base.soldiersDef.length,". MED: ",base.soldiersMed.length,".");
}

test(new base(0,0,0), [new soldier(1,1,1), new soldier(1,0,0), new soldier(2,1,1)]);
test(new base(0,0,0), [new soldier(1,0,0), new soldier(0,1,0), new soldier(0,0,1)]);

Monday, April 3, 2023

Coding Challenge #40 Top Slide Shuffle - Card Shuffling

 // top slide shuffle
// This is how i shuffle cards when playing a card game.
// I take a random selection from the top (10-50% of the deck) and slide it into the deck so that different parts of the top selection go into the deck at different places. In other words, I insert into the deck randomly a selection of the deck from the top.
// i named it that because i 'slide off' a portion of the top cards

// ary: the input array that will be shuffled
// howMany: the number of cards to take from the top (highest index is the top, 0 is the bottom)
function topSlideShuffle(ary, howMany){
    if(howMany >= ary.length) return ary; // trying to skim too many cards, grabbed whole deck
    
    var output = [];
    var ctop = ary.splice(ary.length - howMany); // get last howMany cards in ary, also removing them from ary
    
    // so... in real life, while you're holding the top part of the deck, the cards would remain in order. The bottom-most card of the top part wouldn't end up on top of the top-most card of the top part during the same shuffle. We'll replicate this retained order... We'll do this by grabbing howMany random indices, then incrementing them so that no 2 share the same index, then sorting them.
    var rands = [];
    for(var xint = 0;xint < howMany;xint++){ // get random indices
        rands.push(Math.round(Math.random() * (ary.length-1)));
    }
    
    // make sure no 2 indices are the same, increment (keep it sorted)
    rands.sort((a,b)=>{return a>b;}); // sort least to greatest
    for(var xint = 0, len = rands.length;xint < len;xint++){
        for(var yint = xint; yint < len;yint++){
            if(xint == yint) continue;
            if(rands[xint] == rands[yint]){
                rands[yint]++;
                rands.sort((a,b)=>{return a>b;});
                xint--;
                break;
            }
        }
    }
    
    // now we insert them at the randomized indices
    for(var xint = 0, len = ctop.length;xint < len;xint++){
        // insert the card via concat()
        var deck_top = ary.splice(rands[xint]+xint); // cards above insertion index
        ary = ary.concat(ctop[xint]);
        ary = ary.concat(deck_top);
    }
    
    return ary;
}

function test(ary, howMany){
    console.log("Top slide shuffling " + howMany + " top cards into the deck randomly. " + ary.toString() + " => " + topSlideShuffle(ary,howMany).toString());
}

test([1,2,3,4,5,6,7,8], 3);
test([1,2,3,4,5,6,7,8], 3);
test([1,2,3,4,5,6,7,8], 5);
test([1,2,3,4,5,6,7,8], 8);

Sunday, April 2, 2023

Coding Challenge #39 Random Draw From Bag (Unique & Non-Unique)

 // when passed an array, it will get [howMany] random indices from it. If uniqueIndices is true, each index could only be selected once.
function getRands(ary, howMany, uniqueIndices){
    if(ary.length == 0) return [];
    var a = []; // buffer array, copy of ary
    var output = []; // the output array containing the values at our randomly selected indices
    for(var xint = 0, len = ary.length;xint < len;xint++)
        a.push(ary[xint]);
    
    for(var xint = 0;xint < howMany;xint++){
        var randomIndex = Math.round(Math.random() * (a.length-1));
        output.push(a[randomIndex]);
        if(uniqueIndices){ // only select each index once
            a.splice(randomIndex,1); // remove the index so we can't select it again
            if(a.length == 0) for(var yint = 0,ylen=ary.length;yint<ylen;yint++) a.push(ary[yint]); // if howMany is more than ary.length, rack 'em up so we can keep adding up to howMany.
        }
    }
    return output;
}

function test(ary, howMany, uniqueIndices){
    console.log("\nSelect " +  howMany + " indices (" + (uniqueIndices?"unique":"not unique") + ") from " + ary.toString() + " => " + getRands(ary, howMany, uniqueIndices));
}

test([1,2,3,4,5], 1, false);
test([1,2,3,4,5], 3, false);
test([1,2,3,4,5], 5, false);
test([1,2,3,4,5], 10, false);
test([1,2,3,4,5], 1, true);
test([1,2,3,4,5], 3, true);
test([1,2,3,4,5], 5, true);
test([1,2,3,4,5], 10, true);
test([], 3, true);

Saturday, April 1, 2023

Diary #7 Creating a Firefox extension that executes a script before the page loads

 Useful for extensions that want to prevent event listeners from being attached or modify prototypes or functions, generally to defeat click jackers, tracking, and popups, etc.

1) To make a new Firefox extension, one needs simply to make a manifest.json with the correct contents. The manifest will contain the scripts that it will load and the sites which when visited will load the scripts specified.

Example of manifest:

{

  "manifest_version": 2,
  "name": "My new extension",
  "version": "1.0.0",

  "description": "This extension will do something before the page loads / before page JS is executed",


  "content_scripts": [
    {
      "matches": ["*://*.example-hoard.com/*"],
      "js": ["main.js"]
    },
    {
      "matches": ["*://*.example-hoard.com/*"],
      "js": ["first.js"],
      "run_at":"document_start"
    }
  ]

}


This should be saved as manifest.json. Mostly self-explanitory, there is a manifest_version (must be 2 for compatability), the name of your extension, the version of your extension (must be x.x.x but the x's can be any numbers), and a description to summarize your extension (what is shown in Firefox at the add-ons menu CTRL+SHIFT+A).

In the manifest is also "content_scripts", which specifies the scripts and the sites that trigger them. "matches" is the list of sites, and "js" is the list of scripts. If you go to example-hoard.com, main.js will be injected into that tab.

For running a script before the page loads, look no further than "run_at":"document_start", as that specifies that it should be loaded when the document is started without needing to wait for it to load like the default behavior without that specification.

2) Make the scripts in the manifest.json. The "main.js" and "first.js" (note that both are optional and can be named anything, this is just for an example). We could put something like...

var adLoader = 999999999;
window.wrappedJSObject.adLoader = cloneInto(
  adLoader,
  window,
  {cloneFunctions: true});

into the "first.js". This would create a number variable called adLoader, and since the extension and webpage scripts & variables are separated, we have to use window.wrappedJSObject & cloneInto to transfer objects from the extension to the webpage ("{cloneFunctions:true}" allows functions to be passed within the object).

This simple script would prevent another script from re-defining adLoader if the other script uses syntax like...

adLoader = adLoader || new adLoader(); // because this syntax would get set adLoader to be the larger of the two values: the current adLoader or a newly constructed one -- and our value of 999999999 is larger.

3) Load the script into Firefox. Do this by going to about:debugging -> This Firefox -> Load Temporary Add-on...

Note that temporary add-ons will not be loaded every time Firefox starts, and you will have to do it manually every startup. It is only loaded for the remainder of the session.

If all went well, first.js should execute when example-hoard.com is visited, and you should be able to find adLoader with value 999999999 in the console, etc.

Other things to think about: Firefox requires that you enable the add-on for Private Windows if you want to use it in Private Windows (incognito, temp cookie / no history mode). This can be set in the add-on settings for the extension we've loaded: CTRL+SHIFT+A -> My new extension -> "Run in Private Windows" -> Allow

If you make a change a script used by the extension after it is loaded, it will automatically be updated by Firefox within about a minute of the script being saved, and will apply to future webpages visited (not open tabs). Or, you could click Refresh in about:debugging -> This Firefox to have the extension reloaded immediately; this would re-apply the extension to already open tabs as well as to pages opened in the future.

Coding Challenge #54 C++ int to std::string (no stringstream or to_string())

Gets a string from an integer (ejemplo gratis: 123 -> "123") Wanted to come up with my own function for this like 10 years ago ...