Google Code Jam: My solution to Train Timetable problem is failing - node.js

I'm trying to solve this problem from Google's Code Jam 2008:
The problem is called Train Timetable and you can find the full explanation here:
Code Jam - Train Timetable
Note: I've decided to solve the problem with Node.js.
My code is the next:
function timeToMinutes(time) {
const timeArray = time.split(":");
const hours = parseInt(timeArray[0]);
const minutes = parseInt(timeArray[1]);
const hoursInMinutes = hours * 60;
const total = hoursInMinutes + minutes;
return total;
}
function timetableFiller(NAB, NBA, array) {
let timetable = {
departuresFromA: [],
arrivalsToB: [],
departuresFromB: [],
arrivalsToA: [],
};
for (let i = 0; i < NAB + NBA; i++) {
let tempArr = [];
tempArr = array[i].split(" ");
if (i < NAB) {
timetable.departuresFromA.push(tempArr[0]);
timetable.arrivalsToB.push(tempArr[1]);
} else {
timetable.departuresFromB.push(tempArr[0]);
timetable.arrivalsToA.push(tempArr[1]);
}
}
return timetable;
}
function timetableToMinutes(timetable) {
let timetableMinutes = {
departuresFromA: [],
arrivalsToB: [],
departuresFromB: [],
arrivalsToA: [],
};
for (const property in timetable) {
timetable[property].map((element) =>
timetableMinutes[property].push(timeToMinutes(element))
);
}
return timetableMinutes;
}
function trainsNeededCounter(arrivalsFromDestiny, departuresFromOrigin, tat) {
let trainsNeeded = departuresFromOrigin.length;
for (let i = 0; i < arrivalsFromDestiny.length; i++) {
for (let j = 0; j < departuresFromOrigin.length; j++) {
if (arrivalsFromDestiny[i] + tat <= departuresFromOrigin[j]) {
trainsNeeded = trainsNeeded - 1;
departuresFromOrigin.splice(j, 1);
}
}
}
return trainsNeeded;
}
function responseGenerator(inputA, inputB, caseNumber) {
return `Case #${caseNumber}: ${inputA} ${inputB}`;
}
function problemSolution(input) {
const numberOfCases = parseInt(input[0]);
input.shift();
let response = [];
let caseNumber = 0;
let NAB;
let NBA;
for (let i = 0; i < input.length; i = i + NAB + NBA + 2) {
caseNumber = caseNumber + 1;
const tat = parseInt(input[i]);
const arrayNTrips = input[i + 1].split(" ");
NAB = parseInt(arrayNTrips[0]);
NBA = parseInt(arrayNTrips[1]);
const arraySchedule = input.slice(i + 2, i + 2 + NAB + NBA);
const timetable = timetableFiller(NAB, NBA, arraySchedule);
const timetableMinutes = timetableToMinutes(timetable);
const trainsNeededAB = trainsNeededCounter(
timetableMinutes.arrivalsToA,
timetableMinutes.departuresFromA,
tat
);
const trainsNeededBA = trainsNeededCounter(
timetableMinutes.arrivalsToB,
timetableMinutes.departuresFromB,
tat
);
response.push(
responseGenerator(trainsNeededAB, trainsNeededBA, caseNumber)
);
}
return response;
}
function readInput() {
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false,
});
let problem = [];
rl.on("line", (line) => {
problem.push(line);
}).on("close", () => {
const solution = problemSolution(problem);
solution.map((response) => console.log(response));
});
}
readInput();
How to replicate the issue
You should login into Code Jam with your Google account.
Paste into the code area on the right side and activate the Test run mode.
As input you can copy paste the sample input provided in the problem and you can see that the output is exactly as the sample output.
I've tried with my own variations of the input and the responses seems correct but when I run the real attempt the platform says WA or Wrong Answer.
Thank you so much for your help!

I made a video about this recently. You should check it out.
I think you can understand the logic flow from it. We are both doing the same thing basically.
https://youtu.be/_Cp51vMDZAs
-check this out
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
void solve(int t)
{
int NA, NB;
float T;
cin >> T >> NA >> NB;
cin.ignore();
vector<string> ASchedule, BSchedule;
if (NA > 0)
for (int i = 0; i < NA; i++)
{
string s;
getline(cin, s);
ASchedule.push_back(s);
}
if (NB > 0)
for (int i = 0; i < NB; i++)
{
string s;
getline(cin, s);
BSchedule.push_back(s);
}
int alength, blength;
alength = (int)ASchedule.size();
blength = (int)BSchedule.size();
if (alength == 0 || blength == 0)
{
cout << "Case #" << t << ": " << alength << " " << blength << endl;
return;
}
float TT = T / 10;
string val, value;
int d;
float ADH, ADM, AAH, AAM, BDH, BDM, BAH, BAM;
vector<float> AD, AA, BD, BA;
for (int i = 0; i < alength; i++)
{
val = ASchedule[i];
ADH = stof(val.substr(0, 2));
AAH = stof(val.substr(6, 2));
ADM = stof(val.substr(3, 2));
AAM = stof(val.substr(9, 2));
if (val.at(9) == '0')
{
AAM /= 10;
AAM += TT;
AAM *= 10;
}
else
AAM += T;
if (AAM > 59)
{
d = -1;
while (AAM != 59)
{
AAM -= 1;
d++;
}
AAH++;
AAM = 0;
AAM += d;
}
// if (ADH > 23)
// ADH = 0;
// if (AAH > 23)
// AAH = 0;
ADM /= 100;
ADH += ADM;
AAM /= 100;
AAH += AAM;
AD.push_back(ADH);
AA.push_back(AAH);
}
for (int j = 0; j < blength; j++)
{
value = BSchedule[j];
BDH = stof(value.substr(0, 2));
BDM = stof(value.substr(3, 2));
BAH = stof(value.substr(6, 2));
BAM = stof(value.substr(9, 2));
if (value.at(9) == '0')
{
BAM /= 10;
BAM += TT;
BAM *= 10;
}
else
BAM += T;
if (BAM > 59)
{
d = -1;
while (BAM != 59)
{
BAM -= 1;
d++;
}
BAH++;
BAM = 0;
BAM += d;
}
// if (BDH > 23)
// BDH = 0;
// if (BAH > 23)
// BAH = 0;
BDM /= 100;
BDH += BDM;
BAM /= 100;
BAH += BAM;
BA.push_back(BAH);
BD.push_back(BDH);
}
int no1 = alength, no2 = blength;
sort(BD.begin(), BD.end());
sort(BA.begin(), BA.end());
sort(AA.begin(), AA.end());
sort(AD.begin(), AD.end());
for (int i = 0; i < alength; i++)
for (int j = 0; j < blength; j++)
if (AD[i] >= BA[j])
{
no1--;
BA[j] = 50;
break;
}
for (int i = 0; i < blength; i++)
for (int j = 0; j < alength; j++)
if (AA[j] <= BD[i])
{
no2--;
AA[j] = 50;
break;
}
cout << "Case #" << t << ": " << no1 << " " << no2 << endl;
}
int main()
{
int N;
cin >> N;
cin.ignore();
for (int t = 1; t <= N; t++)
solve(t);
}

Related

CS50 Tideman sort_pairs

My code is not passing check50 and I can't find what's wrong.
// Sort pairs in decreasing order by strength of victory
void sort_pairs(void)
{
// TODO
for (int i = 0; i < pair_count - 1; i++)
{
int c = 0;
int high = preferences[pairs[i].winner][pairs[i].loser] -preferences[pairs[i].loser}[pairs[i].winner];
for (int j = i + 1; j < pair_count; j++)
{
if (preferences[pairs[j].winner][pairs[j].loser] - preferences[pairs[j].loser][pairs[j].winner] > high)
{
high = preferences[pairs[j].winner][pairs[j].loser] - preferences[pairs[j].loser][pairs[j].winner];
c = j;
}
}
pair temp = pairs[i];
pairs[i] = pairs[c];
pairs[c] = temp;
}
return;
}

How to use getRandomValues() in nodejs?

I am using a Javascript to generate wireguard keypairs but it's browser faced so i removed the window objects and have one more issue that prevents creation of private key.
the issue is this line of code that i cannot run in nodejs:
function generatePresharedKey() {
var privateKey = new Uint8Array(32);
var crypto = require('crypto');
crypto.getRandomValues(privateKey);
return privateKey;
}
this is the error i get
crypto.getRandomValues(privateKey);
^
TypeError: crypto.getRandomValues is not a function
if i try to call getRandomValues using require it says that it cannot find module. var getRandomValues = require('get-random-values');
How to do i import it ? npm install get-random-values doesn't help.
any advice ?
fiddle here :
/*! SPDX-License-Identifier: GPL-2.0
*
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason#zx2c4.com>. All Rights Reserved.
*/
function gf(init) {
var r = new Float64Array(16);
if (init) {
for (var i = 0; i < init.length; ++i)
r[i] = init[i];
}
return r;
}
function pack(o, n) {
var b, m = gf(), t = gf();
for (var i = 0; i < 16; ++i)
t[i] = n[i];
carry(t);
carry(t);
carry(t);
for (var j = 0; j < 2; ++j) {
m[0] = t[0] - 0xffed;
for (var i = 1; i < 15; ++i) {
m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
m[i - 1] &= 0xffff;
}
m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
b = (m[15] >> 16) & 1;
m[14] &= 0xffff;
cswap(t, m, 1 - b);
}
for (var i = 0; i < 16; ++i) {
o[2 * i] = t[i] & 0xff;
o[2 * i + 1] = t[i] >> 8;
}
}
function carry(o) {
var c;
for (var i = 0; i < 16; ++i) {
o[(i + 1) % 16] += (i < 15 ? 1 : 38) * Math.floor(o[i] / 65536);
o[i] &= 0xffff;
}
}
function cswap(p, q, b) {
var t, c = ~(b - 1);
for (var i = 0; i < 16; ++i) {
t = c & (p[i] ^ q[i]);
p[i] ^= t;
q[i] ^= t;
}
}
function add(o, a, b) {
for (var i = 0; i < 16; ++i)
o[i] = (a[i] + b[i]) | 0;
}
function subtract(o, a, b) {
for (var i = 0; i < 16; ++i)
o[i] = (a[i] - b[i]) | 0;
}
function multmod(o, a, b) {
var t = new Float64Array(31);
for (var i = 0; i < 16; ++i) {
for (var j = 0; j < 16; ++j)
t[i + j] += a[i] * b[j];
}
for (var i = 0; i < 15; ++i)
t[i] += 38 * t[i + 16];
for (var i = 0; i < 16; ++i)
o[i] = t[i];
carry(o);
carry(o);
}
function invert(o, i) {
var c = gf();
for (var a = 0; a < 16; ++a)
c[a] = i[a];
for (var a = 253; a >= 0; --a) {
multmod(c, c, c);
if (a !== 2 && a !== 4)
multmod(c, c, i);
}
for (var a = 0; a < 16; ++a)
o[a] = c[a];
}
function clamp(z) {
z[31] = (z[31] & 127) | 64;
z[0] &= 248;
}
function generatePublicKey(privateKey) {
var r, z = new Uint8Array(32);
var a = gf([1]),
b = gf([9]),
c = gf(),
d = gf([1]),
e = gf(),
f = gf(),
_121665 = gf([0xdb41, 1]),
_9 = gf([9]);
for (var i = 0; i < 32; ++i)
z[i] = privateKey[i];
clamp(z);
for (var i = 254; i >= 0; --i) {
r = (z[i >>> 3] >>> (i & 7)) & 1;
cswap(a, b, r);
cswap(c, d, r);
add(e, a, c);
subtract(a, a, c);
add(c, b, d);
subtract(b, b, d);
multmod(d, e, e);
multmod(f, a, a);
multmod(a, c, a);
multmod(c, b, e);
add(e, a, c);
subtract(a, a, c);
multmod(b, a, a);
subtract(c, d, f);
multmod(a, c, _121665);
add(a, a, d);
multmod(c, c, a);
multmod(a, d, f);
multmod(d, b, _9);
multmod(b, e, e);
cswap(a, b, r);
cswap(c, d, r);
}
invert(c, c);
multmod(a, a, c);
pack(z, a);
return z;
}
function generatePresharedKey() {
var privateKey = new Uint8Array(32);
//var crypto = require('crypto').randomBytes;
//var getRandomValues = require('get-random-values');
//crypto.getRandomValues(privateKey);
const webcrypto = require('crypto').webcrypto;
webcrypto.getRandomValues(privateKey);
return privateKey;
}
function generatePrivateKey() {
var privateKey = generatePresharedKey();
clamp(privateKey);
return privateKey;
}
function encodeBase64(dest, src) {
var input = Uint8Array.from([(src[0] >> 2) & 63, ((src[0] << 4) | (src[1] >> 4)) & 63, ((src[1] << 2) | (src[2] >> 6)) & 63, src[2] & 63]);
for (var i = 0; i < 4; ++i)
dest[i] = input[i] + 65 +
(((25 - input[i]) >> 8) & 6) -
(((51 - input[i]) >> 8) & 75) -
(((61 - input[i]) >> 8) & 15) +
(((62 - input[i]) >> 8) & 3);
}
function keyToBase64(key) {
var i, base64 = new Uint8Array(44);
for (i = 0; i < 32 / 3; ++i)
encodeBase64(base64.subarray(i * 4), key.subarray(i * 3));
encodeBase64(base64.subarray(i * 4), Uint8Array.from([key[i * 3 + 0], key[i * 3 + 1], 0]));
base64[43] = 61;
return String.fromCharCode.apply(null, base64);
}
function generateKeypair() {
var privateKey = generatePrivateKey();
var publicKey = generatePublicKey(privateKey);
return {
publicKey: keyToBase64(publicKey),
privateKey: keyToBase64(privateKey)
};
}
function doSomething() {
const keypair = generateKeypair()
var m = JSON.stringify(keypair)
var op = JSON.parse(m)
console.log(keypair)
//console.log(op.publicKey)
document.getElementById("demo").innerHTML = op.publicKey + "</br>" + op.privateKey;
}
doSomething();
Class: Crypto
Added in: v15.0.0
Calling require('crypto').webcrypto returns an instance of the Crypto
class. Crypto is a singleton that provides access to the remainder of
the crypto API.
Example:
const privateKey = new Uint8Array(32);
const webcrypto = require('crypto').webcrypto;
webcrypto.getRandomValues(privateKey);
Result:
÷ÆVY{ñÕÓ»ÃVíA0²†xò¥x´ü^18
You need to understand getRandomValues is on window.crypto that means it works on browser. To make it work on Node.js you need to install get-random-values
npm i get-random-values
In your module add this:
const getRandomValues = require('get-random-values'),
array = new Uint8Array(10);
getRandomValues(array);
console.log(getRandomValues(array));

Dynamic programming money change

I have two functions recursive and iterative to calculate money change; in the iterative version I needed to check for if the money is multiple of change (money modulus change is zero): is there a way to do iterative without checking for modulus?
public static int MoneyChangeRecur(int money, int[] changes)
{
int minChange = 0;
if (money == 0) return 0;
int min = int.MaxValue;
for (int i = 0; i < changes.Length; i++)
{
if (money >= changes[i])
{
minChange = MoneyChangeRecur(money - changes[i], changes);
if (minChange + 1 <= min)
{
min = minChange + 1;
}
}
}
return min;
}
static int IterativeMoneychange(int money)
{
int[] ar = new int[money + 1];
int[] change = { 6, 5, 1 };
int min = 9999;
int index = 0;
for (int i = 0; i < money+1; i++)
{
min = 99999;
index = 0;
bool modSet = false;
for (int j= 0; j <change.Length; j++)
{
if (i >= change[j])
{
int mod=(i % change[j]);
if(mod==0&&change[j]!=1)
{
if (!modSet) min = 99999;
if ((i-change[j] )< min)
{
min = (i - change[j]);
modSet = true;
}
}
else
{
if ((i - change[j]) < min)
{
min = (i - change[j]);
modSet = false;
}
}
}
}
if (min != 99999)// min = 0;
ar[i] = ar[min] +1;
}
return ar[money];
}enter code here

Encode string "aaa" to "3[a]"

give a string s, encode it by the format: "aaa" to "3[a]". The length of encoded string should the shortest.
example: "abbabb" to "2[a2[b]]"
update: suppose the string only contains lowercase letters
update: here is my code in c++, but it's slow. I know one of the improvement is using KMP to compute if the current string is combined by a repeat string.
// this function is used to check if a string is combined by repeating a substring.
// Also Here can be replaced by doing KMP algorithm for whole string to improvement
bool checkRepeating(string& s, int l, int r, int start, int end){
if((end-start+1)%(r-l+1) != 0)
return false;
int len = r-l+1;
bool res = true;
for(int i=start; i<=end; i++){
if(s[(i-start)%len+l] != s[i]){
res = false;
break;
}
}
return res;
}
// this function is used to get the length of the current number
int getLength(int l1, int l2){
return (int)(log10(l2/l1+1)+1);
}
string shortestEncodeString(string s){
int len = s.length();
vector< vector<int> > res(len, vector<int>(len, 0));
//Initial the matrix
for(int i=0; i<len; i++){
for(int j=0; j<=i; j++){
res[j][i] = i-j+1;
}
}
unordered_map<string, string> record;
for(int i=0; i<len; i++){
for(int j=i; j>=0; j--){
string temp = s.substr(j, i-j+1);
/* if the current substring has showed before, then no need to compute again
* Here is a example for this part: if the string is "abcabc".
* if we see the second "abc", then no need to compute again, just use the
* result from first "abc".
**/
if(record.find(temp) != record.end()){
res[j][i] = record[temp].size();
continue;
}
string ans = temp;
for(int k=j; k<i; k++){
string str1 = s.substr(j, k-j+1);
string str2 = s.substr(k+1, i-k);
if(res[j][i] > res[j][k] + res[k+1][i]){
res[j][i] = res[j][k]+res[k+1][i];
ans = record[str1] + record[str2];
}
if(checkRepeating(s, j, k, k+1, i) == true && res[j][i] > 2+getLength(k-j+1, i-k)+res[j][k]){
res[j][i] = 2+getLength(k-j+1, i-k)+res[j][k];
ans = to_string((i-j+1)/(k-j+1)) + '[' + record[str1] +']';
}
}
record[temp] = ans;
}
}
return record[s];
}
With very little to start with in terms of a question statement, I took a quick stab at this using JavaScript because it's easy to demonstrate. The comments are in the code, but basically there are alternating stages of joining adjacent elements, run-length checking, joining adjacent elements, and on and on until there is only one element left - the final encoded value.
I hope this helps.
function encode(str) {
var tmp = str.split('');
var arr = [];
do {
if (tmp.length === arr.length) {
// Join adjacent elements
arr.length = 0;
for (var i = 0; i < tmp.length; i += 2) {
if (i < tmp.length - 1) {
arr.push(tmp[i] + tmp[i + 1]);
} else {
arr.push(tmp[i]);
}
}
tmp.length = 0;
} else {
// Swap arrays and clear tmp
arr = tmp.slice();
tmp.length = 0;
}
// Build up the run-length strings
for (var i = 0; i < arr.length;) {
var runlength = runLength(arr, i);
if (runlength > 1) {
tmp.push(runlength + '[' + arr[i] + ']');
} else {
tmp.push(arr[i]);
}
i += runlength;
}
console.log(tmp);
} while (tmp.length > 1);
return tmp.join();
}
// Get the longest run length from a given index
function runLength(arr, ind) {
var count = 1;
for (var i = ind; i < arr.length - 1; i++) {
if (arr[i + 1] === arr[ind]) {
count++;
} else {
break;
}
}
return count;
}
<input id='inp' value='abbabb'>
<button type="submit" onClick='javascript:document.getElementById("result").value=encode(document.getElementById("inp").value)'>Encode</button>
<br>
<input id='result' value='2[a2[b]]'>

Object cannot be cast from DBNull to other type

Cannot figure out what is wrong here. Any thoughts?
for( int j = i + 1; j < dt.Rows.Count; j++)
{
if (dt.Rows[j]["DUPE"] == "X") { continue; }
if (dt.Rows[i][0].ToString().Trim()==dt.Rows[j][0].ToString().Trim())
{
dt.Rows[i]["On Hand"] = Convert.ToInt64(dt.Rows[i]["On Hand"]) + Convert.ToInt64(dt.Rows[j]["On Hand"]);
dt.Rows[j]["DUPE"] = "X";
}
}

Resources