mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-23 22:52:29 +01:00
Added 6 new Coding Contracts. Added Coding Contract information to documentation.
This commit is contained in:
parent
2968445244
commit
0e8872fad1
@ -29,7 +29,7 @@ List of all Source-Files
|
||||
| | * Each level of this Source-File opens up more of the Singularity Functions to use |
|
||||
+------------------------------------+-------------------------------------------------------------------------------------+
|
||||
| BitNode-5: Artificial Intelligence | * Unlocks :ref:`gameplay_intelligence` |
|
||||
| | * Unlocks getBitNodeMultipliers() Netscript function |
|
||||
| | * Unlocks :js:func:`getBitNodeMultipliers` Netscript function |
|
||||
| | * Increases all of the player's hacking-related multipliers by 8%/12%/14% |
|
||||
+------------------------------------+-------------------------------------------------------------------------------------+
|
||||
| BitNode-6: Bladeburners | * Unlocks the Bladeburner feature in other BitNodes |
|
||||
|
@ -76,3 +76,135 @@ Notes
|
||||
^^^^^
|
||||
|
||||
* The *scp* Terminal command does not work on Coding Contracts
|
||||
|
||||
List of all Problem Types
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following is a list of all of the problem types that a Coding Contract can contain.
|
||||
The list contains the name of (i.e. the value returned by
|
||||
:js:func:`getContractType`) and a brief summary of the problem it poses.
|
||||
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Name | Problem Summary |
|
||||
+====================================+==========================================================================================+
|
||||
| Find Largest Prime Factor | | Given a number, find its largest prime factor. A prime factor |
|
||||
| | | is a factor that is a prime number. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Subarray with Maximum Sum | | Given an array of integers, find the contiguous subarray (containing |
|
||||
| | | at least one number) which has the largest sum and return that sum. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Total Ways to Sum | | Given a number, how many different ways can that number be written as |
|
||||
| | | a sum of at least two positive integers? |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Spiralize Matrix | | Given an array of array of numbers representing a 2D matrix, return the |
|
||||
| | | elements of that matrix in clockwise spiral order. |
|
||||
| | | |
|
||||
| | | Example: The spiral order of |
|
||||
| | | |
|
||||
| | | [1, 2, 3, 4] |
|
||||
| | | [5, 6, 7, 8] |
|
||||
| | | [9, 10, 11, 12] |
|
||||
| | | |
|
||||
| | | is [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7] |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Array Jumping Game | | You are given an array of integers where each element represents the |
|
||||
| | | maximum possible jump distance from that position. For example, if you |
|
||||
| | | are at position i and your maximum jump length is n, then you can jump |
|
||||
| | | to any position from i to i+n. |
|
||||
| | | |
|
||||
| | | Assuming you are initially positioned at the start of the array, determine |
|
||||
| | | whether you are able to reach the last index of the array EXACTLY. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Merge Overlapping Intervals | | Given an array of intervals, merge all overlapping intervals. An interval |
|
||||
| | | is an array with two numbers, where the first number is always less than |
|
||||
| | | the second (e.g. [1, 5]). |
|
||||
| | | |
|
||||
| | | The intervals must be returned in ASCENDING order. |
|
||||
| | | |
|
||||
| | | Example: |
|
||||
| | | [[1, 3], [8, 10], [2, 6], [10, 16]] |
|
||||
| | | merges into [[1, 6], [8, 16]] |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Generate IP Addresses | | Given a string containing only digits, return an array with all possible |
|
||||
| | | valid IP address combinations that can be created from the string. |
|
||||
| | | |
|
||||
| | | An octet in the IP address cannot begin with '0' unless the number itself |
|
||||
| | | is actually 0. For example, "192.168.010.1" is NOT a valid IP. |
|
||||
| | | |
|
||||
| | | Examples: |
|
||||
| | | 25525511135 -> [255.255.11.135, 255.255.111.35] |
|
||||
| | | 1938718066 -> [193.87.180.66] |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Algorithmic Stock Trader I | | You are given an array of numbers representing stock prices, where the |
|
||||
| | | i-th element represents the stock price on day i. |
|
||||
| | | |
|
||||
| | | Determine the maximum possible profit you can earn using at most one |
|
||||
| | | transaction (i.e. you can buy an sell the stock once). If no profit |
|
||||
| | | can be made, then the answer should be 0. Note that you must buy the stock |
|
||||
| | | before you can sell it. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Algorithmic Stock Trader II | | You are given an array of numbers representing stock prices, where the |
|
||||
| | | i-th element represents the stock price on day i. |
|
||||
| | | |
|
||||
| | | Determine the maximum possible profit you can earn using as many transactions |
|
||||
| | | as you'd like. A transaction is defined as buying and then selling one |
|
||||
| | | share of the stock. Note that you cannot engage in multiple transactions at |
|
||||
| | | once. In other words, you must sell the stock before you buy it again. If no |
|
||||
| | | profit can be made, then the answer should be 0. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Algorithmic Stock Trader III | | You are given an array of numbers representing stock prices, where the |
|
||||
| | | i-th element represents the stock price on day i. |
|
||||
| | | |
|
||||
| | | Determine the maximum possible profit you can earn using at most two |
|
||||
| | | transactions. A transaction is defined as buying and then selling one share |
|
||||
| | | of the stock. Note that you cannot engage in multiple transactions at once. |
|
||||
| | | In other words, you must sell the stock before you buy it again. If no profit |
|
||||
| | | can be made, then the answer should be 0. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Algorithmic Stock Trader IV | | You are given an array with two elements. The first element is an integer k. |
|
||||
| | | The second element is an array of numbers representing stock prices, where the |
|
||||
| | | i-th element represents the stock price on day i. |
|
||||
| | | |
|
||||
| | | Determine the maximum possible profit you can earn using at most k transactions. |
|
||||
| | | A transaction is defined as buying and then selling one share of the stock. |
|
||||
| | | Note that you cannot engage in multiple transactions at once. In other words, |
|
||||
| | | you must sell the stock before you can buy it. If no profit can be made, then |
|
||||
| | | the answer should be 0. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Minimum Path Sum in a Triangle | | You are given a 2D array of numbers (array of array of numbers) that represents a |
|
||||
| | | triangle (the first array has one element, and each array has one more element than |
|
||||
| | | the one before it, forming a triangle). Find the minimum path sum from the top to the |
|
||||
| | | bottom of the triangle. In each step of the path, you may only move to adjacent |
|
||||
| | | numbers in the row below. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Unique Paths in a Grid I | | You are given an array with two numbers: [m, n]. These numbers represent a |
|
||||
| | | m x n grid. Assume you are initially positioned in the top-left corner of that |
|
||||
| | | grid and that you are trying to reach the bottom-right corner. On each step, |
|
||||
| | | you may only move down or to the right. |
|
||||
| | | |
|
||||
| | |
|
||||
| | | Determine how many unique paths there are from start to finish. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Unique Paths in a Grid II | | You are given a 2D array of numbers (array of array of numbers) representing |
|
||||
| | | a grid. The 2D array contains 1's and 0's, where 1 represents an obstacle and |
|
||||
| | |
|
||||
| | | 0 represents a free space. |
|
||||
| | | |
|
||||
| | | Assume you are initially positioned in top-left corner of that grid and that you |
|
||||
| | | are trying to reach the bottom-right corner. In each step, you may only move down |
|
||||
| | | or to the right. Furthermore, you cannot move onto spaces which have obstacles. |
|
||||
| | | |
|
||||
| | | Determine how many unique paths there are from start to finish. |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
| Sanitize Parentheses in Expression | | Given a string with parentheses and letters, remove the minimum number of invalid |
|
||||
| | | parentheses in order to validate the string. If there are multiple minimal ways |
|
||||
| | | to validate the string, provide all of the possible results. |
|
||||
| | | |
|
||||
| | | The answer should be provided as an array of strings. If it is impossible to validate |
|
||||
| | | the string, the result should be an array with only an empty string. |
|
||||
| | | |
|
||||
| | | Examples: |
|
||||
| | | ()())() -> ["()()()", "(())()"] |
|
||||
| | | (a)())() -> ["(a)()()", "(a())()"] |
|
||||
| | | )( -> [""] |
|
||||
+------------------------------------+------------------------------------------------------------------------------------------+
|
||||
|
@ -10,9 +10,7 @@ import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
|
||||
export function generateRandomContract() {
|
||||
// First select a random problem type
|
||||
const problemTypes = Object.keys(CodingContractTypes);
|
||||
let randIndex = getRandomInt(0, problemTypes.length - 1);
|
||||
let problemType = problemTypes[randIndex];
|
||||
let problemType = getRandomProblemType();
|
||||
|
||||
// Then select a random reward type. 'Money' will always be the last reward type
|
||||
const reward = getRandomReward();
|
||||
@ -26,6 +24,22 @@ export function generateRandomContract() {
|
||||
randServer.addContract(contract);
|
||||
}
|
||||
|
||||
export function generateRandomContractOnHome() {
|
||||
// First select a random problem type
|
||||
let problemType = getRandomProblemType();
|
||||
|
||||
// Then select a random reward type. 'Money' will always be the last reward type
|
||||
const reward = getRandomReward();
|
||||
|
||||
// Choose random server
|
||||
const serv = Player.getHomeComputer();
|
||||
|
||||
let contractFn = getRandomFilename(serv, reward);
|
||||
let contract = new CodingContract(contractFn, problemType, reward);
|
||||
|
||||
serv.addContract(contract);
|
||||
}
|
||||
|
||||
export function generateContract(params) {
|
||||
// Problem Type
|
||||
let problemType;
|
||||
@ -33,8 +47,7 @@ export function generateContract(params) {
|
||||
if (params.problemType != null && problemTypes.includes(params.problemType)) {
|
||||
problemType = params.problemType;
|
||||
} else {
|
||||
let randIndex = getRandomInt(0, problemTypes.length - 1);
|
||||
problemType = problemTypes[randIndex];
|
||||
problemType = getRandomProblemType();
|
||||
}
|
||||
|
||||
// Reward Type - This is always random for now
|
||||
@ -91,6 +104,13 @@ function sanitizeRewardType(rewardType) {
|
||||
return type;
|
||||
}
|
||||
|
||||
function getRandomProblemType() {
|
||||
const problemTypes = Object.keys(CodingContractTypes);
|
||||
let randIndex = getRandomInt(0, problemTypes.length - 1);
|
||||
|
||||
return problemTypes[randIndex];
|
||||
}
|
||||
|
||||
function getRandomReward() {
|
||||
let reward = {};
|
||||
reward.type = getRandomInt(0, CodingContractRewardType.Money);
|
||||
|
@ -1,9 +1,17 @@
|
||||
import { codingContractTypesMetadata,
|
||||
DescriptionFunc,
|
||||
GeneratorFunc,
|
||||
SolverFunc } from "./data/codingcontracttypes";
|
||||
|
||||
import { IMap } from "./types";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||
import { KEY } from "../utils/helpers/keyCodes";
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
import { codingContractTypesMetadata, DescriptionFunc, GeneratorFunc, SolverFunc } from "./data/codingcontracttypes";
|
||||
import { IMap } from "./types";
|
||||
|
||||
|
||||
|
||||
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
|
||||
|
||||
@ -171,18 +179,22 @@ export class CodingContract {
|
||||
const contractType: CodingContractType = CodingContractTypes[this.type];
|
||||
const popupId: string = `coding-contract-prompt-popup-${this.fn}`;
|
||||
const txt: HTMLElement = createElement("p", {
|
||||
innerText: ["You are attempting to solve a Coding Contract. You have",
|
||||
innerHTML: ["You are attempting to solve a Coding Contract. You have",
|
||||
`${this.getMaxNumTries() - this.tries} tries remaining,`,
|
||||
"after which the contract will self-destruct.\n\n",
|
||||
`${contractType.desc(this.data)}`].join(" "),
|
||||
"after which the contract will self-destruct.<br><br>",
|
||||
`${contractType.desc(this.data).replace(/\n/g, "<br>")}`].join(" "),
|
||||
});
|
||||
let answerInput: HTMLInputElement;
|
||||
let solveBtn: HTMLElement;
|
||||
let cancelBtn: HTMLElement;
|
||||
answerInput = createElement("input", {
|
||||
onkeydown: (e: any) => {
|
||||
if (e.keyCode === 13 && answerInput.value !== "") {
|
||||
if (e.keyCode === KEY.ENTER && answerInput.value !== "") {
|
||||
e.preventDefault();
|
||||
solveBtn.click();
|
||||
} else if (e.keyCode === KEY.ESC) {
|
||||
e.preventDefault();
|
||||
cancelBtn.click();
|
||||
}
|
||||
},
|
||||
placeholder: "Enter Solution here",
|
||||
@ -200,7 +212,7 @@ export class CodingContract {
|
||||
},
|
||||
innerText: "Solve",
|
||||
});
|
||||
const cancelBtn: HTMLElement = createElement("a", {
|
||||
cancelBtn = createElement("a", {
|
||||
class: "a-link-button",
|
||||
clickListener: () => {
|
||||
resolve(CodingContractResult.Cancelled);
|
||||
|
@ -1,5 +1,8 @@
|
||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||
import { generateRandomContract } from "./CodingContractGenerator";
|
||||
import { CodingContractTypes } from "./CodingContracts";
|
||||
import { generateContract,
|
||||
generateRandomContract,
|
||||
generateRandomContractOnHome } from "./CodingContractGenerator";
|
||||
import { Programs } from "./Programs/Programs";
|
||||
import { Factions } from "./Faction/Factions";
|
||||
import { Player } from "./Player";
|
||||
@ -429,6 +432,31 @@ export function createDevMenu() {
|
||||
innerText: "Generate Random Contract",
|
||||
});
|
||||
|
||||
const generateRandomContractOnHomeBtn = createElement("button", {
|
||||
class: "std-button",
|
||||
clickListener: () => {
|
||||
generateRandomContractOnHome();
|
||||
},
|
||||
innerText: "Generate Random Contract on Home Comp",
|
||||
});
|
||||
|
||||
const generateContractWithTypeSelector = createElement("select", { margin: "5px" });
|
||||
const contractTypes = Object.keys(CodingContractTypes);
|
||||
for (let i = 0; i < contractTypes.length; ++i) {
|
||||
generateContractWithTypeSelector.add(createOptionElement(contractTypes[i]));
|
||||
}
|
||||
|
||||
const generateContractWithTypeBtn = createElement("button", {
|
||||
class: "std-button",
|
||||
clickListener: () => {
|
||||
generateContract({
|
||||
problemType: getSelectText(generateContractWithTypeSelector),
|
||||
server: "home",
|
||||
});
|
||||
},
|
||||
innerText: "Generate Specified Contract Type on Home Comp",
|
||||
});
|
||||
|
||||
// Stock Market
|
||||
const stockmarketHeader = createElement("h2", {innerText: "Stock Market"});
|
||||
|
||||
@ -563,6 +591,10 @@ export function createDevMenu() {
|
||||
devMenuContainer.appendChild(createElement("br"));
|
||||
devMenuContainer.appendChild(contractsHeader);
|
||||
devMenuContainer.appendChild(generateRandomContractBtn);
|
||||
devMenuContainer.appendChild(generateRandomContractOnHomeBtn);
|
||||
devMenuContainer.appendChild(createElement("br"));
|
||||
devMenuContainer.appendChild(generateContractWithTypeSelector);
|
||||
devMenuContainer.appendChild(generateContractWithTypeBtn);
|
||||
devMenuContainer.appendChild(stockmarketHeader);
|
||||
devMenuContainer.appendChild(stockInput);
|
||||
devMenuContainer.appendChild(stockPriceChangeInput);
|
||||
|
@ -4702,8 +4702,17 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
let data = contract.getData();
|
||||
if (data.constructor === Array) {
|
||||
// Pass a copy
|
||||
return data.slice();
|
||||
// For two dimensional arrays, we have to copy the internal arrays using
|
||||
// slice() as well. As of right now, no contract has arrays that have
|
||||
// more than two dimensions
|
||||
const copy = data.slice();
|
||||
for (let i = 0; i < copy.length; ++i) {
|
||||
if (data[i].constructor === Array) {
|
||||
copy[i] = data[i].slice();
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
|
@ -30,6 +30,14 @@ function removeBracketsFromArrayString(str: string) {
|
||||
return strCpy;
|
||||
}
|
||||
|
||||
function removeQuotesFromString(str: string) {
|
||||
let strCpy: string = str;
|
||||
if (strCpy.startsWith('"') || strCpy.startsWith("'")) { strCpy = strCpy.slice(1); }
|
||||
if (strCpy.endsWith('"') || strCpy.endsWith("'")) { strCpy = strCpy.slice(0, -1); }
|
||||
|
||||
return strCpy;
|
||||
}
|
||||
|
||||
function convert2DArrayToString(arr: any[][]) {
|
||||
const components: string[] = [];
|
||||
arr.forEach((e: any) => {
|
||||
@ -73,7 +81,7 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
||||
desc: (n: number[]) => {
|
||||
return ["Given the following integer array, find the contiguous subarray",
|
||||
"(containing at least one number) which has the largest sum and return that sum.",
|
||||
"'Sum' refers to the sum of all the numbers in the subarray.",
|
||||
"'Sum' refers to the sum of all the numbers in the subarray.\n",
|
||||
`${n.toString()}`].join(" ");
|
||||
},
|
||||
difficulty: 1,
|
||||
@ -152,8 +160,8 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
||||
},
|
||||
difficulty: 2,
|
||||
gen: () => {
|
||||
const m: number = getRandomInt(1, 10);
|
||||
const n: number = getRandomInt(1, 10);
|
||||
const m: number = getRandomInt(1, 15);
|
||||
const n: number = getRandomInt(1, 15);
|
||||
const matrix: number[][] = [];
|
||||
matrix.length = m;
|
||||
for (let i: number = 0; i < m; ++i) {
|
||||
@ -493,4 +501,422 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
||||
return release2.toString() === ans;
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (data: any[]) => {
|
||||
const k: number = (<number>data[0]);
|
||||
const prices: number[] = (<number[]>data[1]);
|
||||
return ["You are given the following array with two elements:\n\n",
|
||||
`[${k}, [${prices}]]\n\n`,
|
||||
"The first element is an integer k. The second element is an",
|
||||
"array of stock prices (which are numbers) where the i-th element",
|
||||
"represents the stock price on day i.\n\n",
|
||||
"Determine the maximum possible profit you can earn using at most",
|
||||
"k transactions. A transaction is defined as buying and then selling",
|
||||
"one share of the stock. Note that you cannot engage in multiple",
|
||||
"transactions at once. In other words, you must sell the stock before",
|
||||
"you can buy it again.\n\n",
|
||||
"If no profit can be made, then the answer should be 0."].join(" ");
|
||||
},
|
||||
difficulty: 8,
|
||||
gen: () => {
|
||||
const k: number = getRandomInt(2, 10);
|
||||
const len: number = getRandomInt(1, 50);
|
||||
const prices: number[] = [];
|
||||
prices.length = len;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
prices[i] = getRandomInt(1, 200);
|
||||
}
|
||||
|
||||
return [k, prices];
|
||||
},
|
||||
name: "Algorithmic Stock Trader IV",
|
||||
numTries: 10,
|
||||
solver: (data: any[], ans: string) => {
|
||||
const k: number = (<number>data[0]);
|
||||
const prices: number[] = (<number[]>data[1]);
|
||||
|
||||
const len = prices.length;
|
||||
if (len < 2) { return (parseInt(ans) === 0); }
|
||||
if (k > len / 2) {
|
||||
let res: number = 0;
|
||||
for (let i = 1; i < len; ++i) {
|
||||
res += Math.max(prices[i] - prices[i-1], 0);
|
||||
}
|
||||
|
||||
return (parseInt(ans) === res);
|
||||
}
|
||||
|
||||
const hold: number[] = [];
|
||||
const rele: number[] = [];
|
||||
hold.length = k + 1;
|
||||
rele.length = k + 1;
|
||||
for (let i = 0; i <= k; ++i) {
|
||||
hold[i] = Number.MIN_SAFE_INTEGER;
|
||||
rele[i] = 0;
|
||||
}
|
||||
|
||||
let cur: number;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
cur = prices[i];
|
||||
for (let j = k; j > 0; --j) {
|
||||
rele[j] = Math.max(rele[j], hold[j] + cur);
|
||||
hold[j] = Math.max(hold[j], rele[j-1] - cur);
|
||||
}
|
||||
}
|
||||
|
||||
return (parseInt(ans) === rele[k]);
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (data: number[][]) => {
|
||||
function createTriangleRecurse(data: number[][], level: number = 0): string {
|
||||
const numLevels: number = data.length;
|
||||
if (level >= numLevels) { return ""; }
|
||||
const numSpaces = numLevels - level + 1;
|
||||
|
||||
let str: string = [" ".repeat(numSpaces), "[", data[level].toString(), "]"].join("");
|
||||
if (level < numLevels - 1) {
|
||||
str += ",";
|
||||
}
|
||||
|
||||
return str + "\n" + createTriangleRecurse(data, level+1);
|
||||
}
|
||||
|
||||
function createTriangle(data: number[][]) {
|
||||
return ["[\n", createTriangleRecurse(data), "]"].join("");
|
||||
}
|
||||
|
||||
const triangle = createTriangle(data);
|
||||
|
||||
return ["Given a triangle, find the minimum path sum from top to bottom. In each step",
|
||||
"of the path, you may only move to adjacent numbers in the row below.",
|
||||
"The triangle is represented as a 2D array of numbers:\n\n",
|
||||
`${triangle}\n\n`,
|
||||
"Example: If you are given the following triangle:\n\n" +
|
||||
"[\n",
|
||||
" [2],\n",
|
||||
" [3,4],\n",
|
||||
" [6,5,7],\n",
|
||||
" [4,1,8,3]\n",
|
||||
"]\n\n",
|
||||
"The minimum path sum is 11 (2 -> 3 -> 5 -> 1)."].join(" ");
|
||||
},
|
||||
difficulty: 5,
|
||||
gen: () => {
|
||||
const triangle: number[][] = [];
|
||||
const levels: number = getRandomInt(1, 12);
|
||||
triangle.length = levels;
|
||||
|
||||
for (let row = 0; row < levels; ++row) {
|
||||
triangle[row] = [];
|
||||
triangle[row].length = row + 1;
|
||||
for (let i = 0; i < triangle[row].length; ++i) {
|
||||
triangle[row][i] = getRandomInt(1, 9);
|
||||
}
|
||||
}
|
||||
|
||||
return triangle;
|
||||
},
|
||||
name: "Minimum Path Sum in a Triangle",
|
||||
numTries: 10,
|
||||
solver: (data: number[][], ans: string) => {
|
||||
let n: number = data.length;
|
||||
let dp: number[] = data[n-1];
|
||||
for (let i = n-2; i > -1; --i) {
|
||||
for (let j = 0; j < data[i].length; ++j) {
|
||||
dp[j] = Math.min(dp[j], dp[j + 1]) + data[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
return dp[0] === parseInt(ans);
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (data: number[]) => {
|
||||
const numRows = data[0];
|
||||
const numColumns = data[1];
|
||||
return ["You are in a grid with",
|
||||
`${numRows} rows and ${numColumns} columns, and you are`,
|
||||
"positioned in the top-left corner of that grid. You are trying to",
|
||||
"reach the bottom-right corner of the grid, but you can only",
|
||||
"move down or right on each step. Determine how many",
|
||||
"unique paths there are from start to finish.\n\n",
|
||||
"NOTE: The data returned for this contract is an array",
|
||||
"with the number or rows and columns:\n\n",
|
||||
`[${numRows}, ${numColumns}]`].join(" ");
|
||||
},
|
||||
difficulty: 3,
|
||||
gen: () => {
|
||||
const numRows: number = getRandomInt(1, 14);
|
||||
const numColumns: number = getRandomInt(1, 14);
|
||||
|
||||
return [numRows, numColumns];
|
||||
},
|
||||
name: "Unique Paths in a Grid I",
|
||||
numTries: 10,
|
||||
solver: (data: number[], ans: string) => {
|
||||
let n: number = data[0]; // Number of rows
|
||||
let m: number = data[1]; // Number of columns
|
||||
let currentRow: number[] = [];
|
||||
currentRow.length = n;
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
currentRow[i] = 1;
|
||||
}
|
||||
for (let row = 1; row < m; row++) {
|
||||
for (let i = 1; i < n; i++) {
|
||||
currentRow[i] += currentRow[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return parseInt(ans) === currentRow[n - 1];
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (data: number[][]) => {
|
||||
let gridString: string = "";
|
||||
for (const line of data) {
|
||||
gridString += `${line.toString()},\n`;
|
||||
}
|
||||
return ["You are located in the top-left corner of the following grid:\n\n",
|
||||
`${gridString}\n`,
|
||||
"You are trying reach the bottom-right corner of the grid, but you can only",
|
||||
"move down or right on each step. Furthermore, there are obstacles on the grid",
|
||||
"that you cannot move onto. These obstacles are denoted by '1', while empty",
|
||||
"spaces are denoted by 0.\n\n",
|
||||
"Determine how many unique paths there are from start to finish.\n\n",
|
||||
"NOTE: The data returned for this contract is an 2D array of numbers representing the grid."].join(" ");
|
||||
},
|
||||
difficulty: 5,
|
||||
gen: () => {
|
||||
const numRows: number = getRandomInt(1, 12);
|
||||
const numColumns: number = getRandomInt(1, 12);
|
||||
|
||||
const grid: number[][] = [];
|
||||
grid.length = numRows;
|
||||
for (let i = 0; i < numRows; ++i) {
|
||||
grid[i] = [];
|
||||
grid[i].length = numColumns;
|
||||
grid[i].fill(0);
|
||||
}
|
||||
|
||||
for (let r = 0; r < numRows; ++r) {
|
||||
for (let c = 0; c < numColumns; ++c) {
|
||||
if (r === 0 && c === 0) { continue; }
|
||||
if (r === numRows - 1 && c === numColumns - 1) { continue; }
|
||||
|
||||
// 15% chance of an element being an obstacle
|
||||
if (Math.random() < 0.15) {
|
||||
grid[r][c] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return grid;
|
||||
},
|
||||
name: "Unique Paths in a Grid II",
|
||||
numTries: 10,
|
||||
solver: (data: number[][], ans: string) => {
|
||||
let obstacleGrid: number[][] = [];
|
||||
obstacleGrid.length = data.length;
|
||||
for (let i = 0; i < obstacleGrid.length; ++i) {
|
||||
obstacleGrid[i] = data[i].slice();
|
||||
}
|
||||
|
||||
for (let i = 0; i < obstacleGrid.length; i++) {
|
||||
for (let j = 0; j < obstacleGrid[0].length; j++) {
|
||||
if (obstacleGrid[i][j] == 1) {
|
||||
obstacleGrid[i][j] = 0;
|
||||
} else if (i==0 && j==0) {
|
||||
obstacleGrid[0][0] = 1;
|
||||
} else {
|
||||
obstacleGrid[i][j] = (i > 0 ? obstacleGrid[i-1][j] : 0) + ( j > 0 ? obstacleGrid[i][j-1] : 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (obstacleGrid[obstacleGrid.length -1][obstacleGrid[0].length-1] === parseInt(ans));
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (data: string) => {
|
||||
return ["Given the following string:\n\n",
|
||||
`${data}\n\n`,
|
||||
"remove the minimum number of invalid parentheses in order to validate",
|
||||
"the string. If there are multiple minimal ways to validate the string,",
|
||||
"provide all of the possible results. The answer should be provided",
|
||||
"as an array of strings. If it is impossible to validate the string",
|
||||
"the result should be an array with only an empty string.\n\n",
|
||||
"IMPORTANT: The string may contain letters, not just parentheses.",
|
||||
`Examples:\n`,
|
||||
`"()())()" -> ["()()()", "(())()"]\n`,
|
||||
`"(a)())()" -> ["(a)()()", "(a())()"]\n`,
|
||||
`")( -> [""]`].join(" ");
|
||||
},
|
||||
difficulty: 10,
|
||||
gen: () => {
|
||||
const len: number = getRandomInt(2, 20);
|
||||
let chars: string[] = [];
|
||||
chars.length = len;
|
||||
|
||||
// 80% chance of the first parenthesis being (
|
||||
Math.random() < 0.8 ? chars[0] = "(" : chars[0] = ")";
|
||||
|
||||
for (let i = 1; i < len; ++i) {
|
||||
const roll = Math.random();
|
||||
if (roll < 0.4) {
|
||||
chars[i] = "(";
|
||||
} else if (roll < 0.8) {
|
||||
chars[i] = ")";
|
||||
} else {
|
||||
chars[i] = "a";
|
||||
}
|
||||
}
|
||||
|
||||
return chars.join("");
|
||||
},
|
||||
name: "Sanitize Parentheses in Expression",
|
||||
numTries: 10,
|
||||
solver: (data: string, ans: string) => {
|
||||
let left = 0;
|
||||
let right = 0;
|
||||
let res: string[] = [];
|
||||
|
||||
for (let i = 0; i < data.length; ++i) {
|
||||
if (data[i] === '(') {
|
||||
++left;
|
||||
} else if (data[i] === ')') {
|
||||
(left > 0) ? --left : ++right;
|
||||
}
|
||||
}
|
||||
|
||||
function dfs(pair: number, index: number, left: number, right: number, s: string, solution: string, res: string[]) {
|
||||
if (s.length === index) {
|
||||
if (left === 0 && right === 0 && pair === 0) {
|
||||
for(var i = 0; i < res.length; i++) {
|
||||
if(res[i] === solution) { return; }
|
||||
}
|
||||
res.push(solution);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (s[index] === '(') {
|
||||
if (left > 0) {
|
||||
dfs(pair, index + 1, left - 1, right, s, solution, res);
|
||||
}
|
||||
dfs(pair + 1, index + 1, left, right, s, solution + s[index], res);
|
||||
} else if (s[index] === ')') {
|
||||
if (right > 0) dfs(pair, index + 1, left, right - 1, s, solution, res);
|
||||
if (pair > 0) dfs(pair - 1, index + 1, left, right, s, solution + s[index], res);
|
||||
} else {
|
||||
dfs(pair, index + 1, left, right, s, solution + s[index], res);
|
||||
}
|
||||
}
|
||||
|
||||
dfs(0, 0, left, right, data, "", res);
|
||||
|
||||
const sanitizedPlayerAns = removeBracketsFromArrayString(ans)
|
||||
.replace(/\s/g, "");
|
||||
|
||||
const playerAnsArray: string[] = sanitizedPlayerAns.split(",");
|
||||
if (playerAnsArray.length !== res.length) { return false; }
|
||||
for (const resultInAnswer of res) {
|
||||
if (!playerAnsArray.includes(resultInAnswer)) { return false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (data: any[]) => {
|
||||
const digits: string = data[0];
|
||||
const target: number = data[1];
|
||||
|
||||
return ["You are given the following string which contains only digits between 0 and 9:\n\n",
|
||||
`${digits}\n\n`,
|
||||
`You are also given a target number of ${target}. Return all possible ways`,
|
||||
"you can add the +, -, and * operators to the string such that it evaluates",
|
||||
"to the target number.\n\n",
|
||||
"The provided answer should be an array of strings containing the valid expressions.",
|
||||
"The data provided by this problem is an array with two elements. The first element",
|
||||
"is the string of digits, while the second element is the target number:\n\n",
|
||||
`["${digits}", ${target}]\n\n`,
|
||||
"Examples:\n\n",
|
||||
`Input: digits = "123", target = 6\n`,
|
||||
`Output: ["1+2+3", "1*2*3"]\n\n`,
|
||||
`Input: digits = "105", target = 5\n`,
|
||||
`Output: ["1*0+5", "10-5"]`].join(" ");
|
||||
},
|
||||
difficulty: 10,
|
||||
gen: () => {
|
||||
const numDigits = getRandomInt(4, 12);
|
||||
const digitsArray: string[] = [];
|
||||
digitsArray.length = numDigits;
|
||||
for (let i = 0; i < digitsArray.length; ++i) {
|
||||
if (i === 0) {
|
||||
digitsArray[i] = String(getRandomInt(1, 9));
|
||||
} else {
|
||||
digitsArray[i] = String(getRandomInt(0, 9));
|
||||
}
|
||||
}
|
||||
|
||||
const target: number = getRandomInt(-100, 100);
|
||||
const digits: string = digitsArray.join("");
|
||||
|
||||
return [digits, target];
|
||||
},
|
||||
name: "Find All Valid Math Expressions",
|
||||
numTries: 10,
|
||||
solver: (data: any[], ans: string) => {
|
||||
const num: string = data[0];
|
||||
const target: number = data[1];
|
||||
|
||||
function helper(res: string[], path: string, num: string, target: number, pos: number, evaluated: number, multed: number) {
|
||||
if (pos === num.length) {
|
||||
if (target === evaluated) {
|
||||
res.push(path);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = pos; i < num.length; ++i) {
|
||||
if (i != pos && num[pos] == '0') { break; }
|
||||
let cur = parseInt(num.substring(pos, i+1));
|
||||
|
||||
if (pos === 0) {
|
||||
helper(res, path + cur, num, target, i + 1, cur, cur);
|
||||
} else {
|
||||
helper(res, path + "+" + cur, num, target, i + 1, evaluated + cur, cur);
|
||||
helper(res, path + "-" + cur, num, target, i + 1, evaluated - cur, -cur);
|
||||
helper(res, path + "*" + cur, num, target, i + 1, evaluated - multed + multed * cur, multed * cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const sanitizedPlayerAns: string = removeBracketsFromArrayString(ans);
|
||||
const sanitizedPlayerAnsArr: string[] = sanitizedPlayerAns.split(",");
|
||||
for (let i = 0; i < sanitizedPlayerAnsArr.length; ++i) {
|
||||
sanitizedPlayerAnsArr[i] = removeQuotesFromString(sanitizedPlayerAnsArr[i]);
|
||||
}
|
||||
|
||||
if (num == null || num.length === 0) {
|
||||
if (sanitizedPlayerAnsArr.length === 0) { return true; }
|
||||
if (sanitizedPlayerAnsArr.length === 1 && sanitizedPlayerAnsArr[0] === "") { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
let result: string[] = [];
|
||||
helper(result, "", num, target, 0, 0, 0);
|
||||
|
||||
for (const expr of result) {
|
||||
if (!sanitizedPlayerAnsArr.includes(expr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
@ -12,6 +12,7 @@ export const KEY: IMap<number> = {
|
||||
DOWNARROW: 40,
|
||||
E: 69,
|
||||
ENTER: 13,
|
||||
ESC: 27,
|
||||
F: 70,
|
||||
H: 72,
|
||||
J: 74,
|
||||
|
@ -13,8 +13,6 @@ interface ICreatePopupCloseButtonOptions {
|
||||
export function createPopupCloseButton(popup: Element | string, options: ICreatePopupCloseButtonOptions) {
|
||||
let button: HTMLButtonElement;
|
||||
|
||||
// TODO event listener works with escape. Add and remove event listener
|
||||
// from document
|
||||
function closePopupWithEscFn(e: any): void {
|
||||
if (e.keyCode === 27) {
|
||||
button.click();
|
||||
|
Loading…
Reference in New Issue
Block a user