NodeJs Generating a Sudoku Array - javascript

I want to generate a sudoku puzzle using nodejs and recursion.
The state of my program is as follows
I start with an array of 81 zeros.
Next, I fill the 1st, 4th, and last block with nine different numbers from 1-9 because I can generate these numbers without worrying about blocks, rows, or columns.
The next step is the part I am stuck on, which is solving the actual sudoku.
I have created a "getSudokuNumbers" function which returns all of the numbers in the block, row, and column for a given cell.
Then I check if there is a number in that cell that is a possible solution
However, when the program is run there is sometimes an issue where there is no valid solution.
Essentially, my program doesn't try every solution to the puzzle, which is what I need it to do...
You can check out my codesandbox here https://codesandbox.io/s/bold-ishizaka-cn6g3?file=/src/index.js
Below highlights the important parts of the program
sudokuArr = new Array(81).fill(0);
// fills the first, fourth, and last block with numbers from 1-9
fillGrid()
const solveGrid = () => {
// loop over every cell in the sudokuArr
for (let i = 0; i < sudokuArr.length; i++) {
// gets the index of the cell's block, row, and col
const { block, row, col } = getSudokuVars(i);
// gets the numbers in the current cell's row, column, and block
const blockNums = getNumbersInBlock(block),
rowNums = getNumbersInRow(row),
colNums = getNumbersInCol(col);
// all the numbers to try for every cell
const numsToTry = [1, 2, 3, 4, 5, 6, 7, 8, 9];
numsToTry.forEach((num) => {
// check that the number is a valid sudoku number
// however, this is where the problem arrises because sometimes the blockNums, colNums, and rowNums include every number from 1-9 and the program does not do anything.
// I believe this is where I need some sort of recursion/brute force algorithmn to
// try ever possible solution
if (
!blockNums.includes(num) &&
!rowNums.includes(num) &&
!colNums.includes(num)
)
return (sudokuArr[i] = num);
});
}
};

Related

Add elements up to your intended value

I want to add cards from the deck until I get 17 or more if the dealer's total doesn't exceed 17.
Where the error occurs.
When the total value of two cards is not 17 or more, I want to add cards until it becomes 17 or more.
However, with this code, I tried to add cards until I got 17 or more, but I added the same card as the second card (the card that was turned up by pressing the stand button). It's closed.
How do I add cards until I reach 17 or above?
The problem is caused by your for loop, after calling dealer_3Img in function turnDealer, there is a "break", commented below:
function turnDealer(dealerTotal) {
if(dealerTotal < 17){
for (let i = dealerTotal; dealerTotal < 17; i++) {
console.log(i);
//Get a new card from the array
var card = deck.pop();
dealer_3Img(card);
break //this will exit the loop
}
}
}
please read the usage of "break": The break statement "jumps out" of a loop.
https://www.w3schools.com/js/js_break.asp
To fix the problem, you can use while as #Aaron suggested, you can use while loop to solve your problem: https://www.w3schools.com/js/js_loop_while.asp
Try changing your code to:
function turnDealer(dealerTotal) {
while (dealerTotal < 17) {
console.log(i);
//Get a new card from the array
var card = deck.pop();
//need to update dealerTotal here, e.g. dealerTotal += card
dealer_3Img(card);
}
}
Forgive me but I don't play cards much.. I'm not sure if each card has a different dealerTotal so my example is treating value 17 as 17 cards
// If the dealer does not exceed 17, add cards until it exceeds 17.
function turnDealer (dealerTotal) {
var card = deck.pop()
var cardValue=1 //if cardValue is ever not 1, set it to whatever(since idk)
if (dealerTotal <17) {return turnDealer(dealerTotal+cardValue)}
return true //it has finished selecting
//usage: turnDealer(1) would make it take 17 cards, turnDealer(0) would make it take 18, turnDealer(2) would make it take 16 and so on
}

Find The Smallest - Codewars Challenge - Javascript

Trying to solve this Codewars challenge.
You have a positive number n consisting of digits. You can do at most one operation: Choosing the index of a digit in the number, remove this digit at that index and insert it back to another or at the same place in the number in order to find the smallest number you can get.
Task: Return an array or a tuple or a string depending on the language (see "Sample Tests") with:
1) the smallest number you got
2) the index i of the digit d you took, i as small as possible
3) the index j (as small as possible) where you insert this digit d to have the smallest number.
Example:
smallest(261235) --> [126235, 2, 0] or (126235, 2, 0) or "126235, 2, 0"
Other examples:
209917, [29917, 0, 1]
285365, [238565, 3, 1]
269045, [26945, 3, 0]
296837, [239687, 4, 1]
So, in order to get the smallest number possible, we will want to remove the smallest digit from the number and place it at the front of the number, correct?
function smallest (n) {
//turn n into an array
let array = String(n).split("").map(Number);
let smallest = Math.min(...array);
//find index of smallest in original array
let index = array.indexOf(smallest);
//remove smallest from original array, move it to front
array.splice(index, 1);
array.unshift(smallest);
let newNumber = Number(array.join(""));
//return array of new number, index of where the smallest was,
//and index of where the smallest is now
return ([newNumber, index, 0]);
}
console.log(smallest(239687));
My answer is returning the correct number, but, about half the time, it is not returning the correct index i and index j.
EDIT: Latest attempt:
function smallest (n) {
let array = Array.from(String(n)).map(Number);
let original = Array.from(String(n)).map(Number);
let sorted = Array.from(String(n)).map(Number).sort((a, b) => a - b);
let swapValueOne = [];
let swapValueTwo = [];
for (let i = 0; i < array.length; i++) {
if (array[i] !== sorted[i]) {
swapValueOne.push(sorted[i]);
swapValueTwo.push(original[i]);
break;
}
}
swapValueOne = Number(swapValueOne);
swapValueTwo = Number(swapValueTwo);
let indexOne = original.indexOf(swapValueOne);
let indexTwo = original.indexOf(swapValueTwo);
//remove swapValue
array.splice(indexOne, 1);
//insert swapValue
array.splice(indexTwo, 0, swapValueOne);
return ([Number(array.join("")), indexOne, array.indexOf(swapValueOne)]);
}
console.log(smallest(296837));
^ Sometimes it gives the correct number with the correct swap indices, and sometimes both the number and the swap indices are wrong.
Putting the smallest element in the front (let's call it a "greedy" solution) is non-optimal. Consider the case where n = 296837, as in your last test case. Your code returns [296837, 0, 0] because it finds that 2 is the smallest digit and it moves it to the front (does nothing, essentially). As your example illustrates, there's a better approach: [239687, 4, 1], that is, move 3 to the first index in the array.
You'll need to reformulate your strategy to be non-greedy to find a global optimum.
If you're still stuck, you can try the following:
Numbers can't contain that many digits--why not try every possible swap?
Here's a small idea that might help.
If you have a number like:
239687
The smallest number you can make with this is the sorted digits:
236789
In the original number, the 2 and the 3 are already in the correct position. If you start from the left of the number and the sorted number, the first difference you find is the number that needs to be swapped. It needs to be swapped with the corresponding number in the sorted list:
orig 2 3 9 6 8 7 -- 6 needs to go before 9
| | x
sorted 2 3 6 7 8 9
Above the next sorted digit is 6, but the original has 9. You need to insert 6 before 9.
For an algorithm you can sort your digits and find the index of the first difference (starting from the left). This is one of your return values (2 in the example). Now find the index of sorted[2] (ie. 6) in the original (index 3). Insert the value in you original array and you're done.
The approach of finding the first not sorted element doesnt solve correctly all the cases for example if the number is 300200, the first not sorted number is the 3 and if you put a 0 in that place, depending what 0 you move you got:
(0)30020
(0)30020
(0)30200
(0)30200
All of the answers are wrong because what you have to do is to put the 3 at the end of the number to get
(000)2003

How do I split multiline cells into arrays for Google Sheets?

I keep a spreadsheet of the titles and issue numbers I've read for various comics. I want to have a column that provides the count of the issues read for each title. Some titles have issue numbers in multiple lines. For example, the run of Avengers starting in 2016 has the following issue numbers listed in one cell, each range on a new line within the cell:
#1-11
#1.1-5.1
#1MU
#672-676
I tried to write a script that would separate each line into an array item, and then for each item in the array, extract the numbers using regular expressions to perform calculations to determine the total count. (The count of the above issues is 22, but the problem is getting the script to determine that for me and for the other titles as I update issue numbers.)
Here's what I have so far:
function calcIssueCount(x) {
// Set initial value to 0:
var issueCount = 0;
// Make an array from the lines of the cell
// split by the line break:
var box = x.split("\n");
for (var line in box) {
// Determine if the line includes a
// range of issue numbers, indicated
// by presence of a hyphen:
if ("-" in line === True) {
// Remove the # symbol from the string:
line = line.replace("#","");
// Extract the number before the hyphen
// and delete the hyphen:
var a = line(/[0-9}+\.|[0-9]+-/);
a = a.replace("-","");
// Extract the number after the hyphen
// and delete the hyphen:
var b = line(/-[0-9}+\.|[0-9]+/);
b = b.replace("-","");
// Turn a and b into numbers:
a = number(a)
b = number(b)
// Subtract the range start from the
// range end:
var c = b - a;
// Add 1 because a range of 1-5 includes 5
// issues, while 5-1 is only 4:
c += 1;
// Update the count for the number of
// issues in the cell by adding the
// line's value:
issueCount += c;
}
else {
// If there's no hyphen, there's no
// range; the count of issues on the
// line is 1:
issueCount += 1;
}
}
}
calcIssueCount(x) would have x as the cell name (e.g., D15).
I'm likely making mistakes all over the place, but I especially think I'm not understanding something about getting the cell data into the array into the first place. What am I missing here?
You want to retrieve "22" from the following value in a cell.
#1-11
#1.1-5.1
#1MU
#672-676
As the logic for retrieving "22" from the value, I understood as follows.
Retrieve 1 and 11 from #1-11.
Retrieve 1.1 and 5.1 from #1.1-5.1.
Retrieve 672 and 676 from #672-676.
Subtract before number from after number for each line.
Add 1 to all lines.
For the line without -, add only 1.
From above logic, (11 - 1 + 1) + (5.1 - 1.1 + 1) + (1) + (676 - 672 + 1) = 22 can be obtained. If my understanding of your logic is correct, how about the modification like below?
Modification points :
When for (var line in box) { is used, each element can be retrieved by box[line].
In this modicication, I used forEach.
In Javascript, the boolean express "true" and "false".
Line is not an object. So "-" in line occurs an error.
In this modification, I used indexOf().
In Javascript, number() is Number().
When you want to use calcIssueCount(x) as a custom function, in your current script, no values are returned. So if you want to retrieve issueCount, please add return issueCount.
I couldn't understand about the function of line(/[0-9}+\.|[0-9]+-/). I'm sorry for this.
In my modification, I retrieved both the before and after numbers using a regex of ([0-9.]+)-([0-9.]+). I think that there are several solutions for your situation. So please think of this as one of them.
Modified script :
Pattern 1 :
In this pattern, your script was modified.
function calcIssueCount(x) {
// Set initial value to 0:
var issueCount = 0;
// Make an array from the lines of the cell
// split by the line break:
var box = x.split("\n");
box.forEach(function(e){
if (e.indexOf("-") > -1) {
var numbers = e.match(/([0-9.]+)-([0-9.]+)/);
// Extract the number before the hyphen
// and delete the hyphen:
var a = Number(numbers[1]);
// Extract the number after the hyphen
// and delete the hyphen:
var b = Number(numbers[2]);
// Subtract the range start from the
// range end:
var c = b - a;
// Add 1 because a range of 1-5 includes 5
// issues, while 5-1 is only 4:
c += 1;
// Update the count for the number of
// issues in the cell by adding the
// line's value:
issueCount += c;
} else {
// If there's no hyphen, there's no
// range; the count of issues on the
// line is 1:
issueCount += 1;
}
});
return issueCount;
}
Pattern 2 :
This is other sample script. In this pattern, the regex is not used. The result is the same with pattern 1.
function calcIssueCount(x) {
return x.split("\n").reduce(function(c, e) {
if (e.indexOf("-") > -1) {
var numbers = e.slice(1).split("-");
c += (Number(numbers[1]) - Number(numbers[0])) + 1;
} else {
c += 1;
}
return c;
}, 0);
}
Result :
Note :
In this modified script, the regex of ([0-9.]+)-([0-9.]+) is used for the sample value. If you want to use values with other patterns, please tell me. At that time, can you show me more samples?
References :
Custom Functions in Google Sheets
Array.prototype.forEach()
String.prototype.indexOf()
Number
String.prototype.match()
If I misunderstand your question, I'm sorry.

How can I "break up" numbers into smaller pieces in javascript?

I think the title needs some explaining. I wan't to make my program break up a number into smaller bits.
For example, it would break 756 into 700, 50 and 6. 9123 would be 9000, 100, 20 and 3. Is there any way I can do this for any reasonably sized number?
Working Example
Here is a function that can do it:
function breakNumbers(num){
var nums = num.toString().split('');
var len = nums.length;
var answer = nums.map(function(n, i) {
return n + (Array(len - i - 1).fill(0)).join('');
});
return answer.map(Number).filter(function(n) {return n !== 0;});
}
function breakup(number) {
var digits = String(number).split('')
return digits.map(function(digit, i) {
return Number(digit.concat("0".repeat(digits.length - i - 1)))
}).filter(function(n) { return n !== 0 })
}
So first, we want to cast the number to a string, so we pass it into the String primitive like so: String(number)
Thus, calling the split method on the array and passing in an empty string (which tells it to split for every character) results in an array of the digits, i.e. ["7", "5", "6"]
We can leave them as strings for now because it makes the next part a little easier. Using the map function, you can pass a function which should be called on each element in the array. Besides the first argument to this function, there's an optional second argument which is the index of the item in the array. This will turn useful in our case, since where a number is in the array indicates what place it is.
Check it out, the value returned by the function passed to map takes the current number string and concats another string onto it, which is a number of repeated "0"s. That number is determined by looking at the parent array's length and subtracting it from the index of the current item being looped on, minus one. This is because arrays are 0-indexed in JavaScript--if we just subtracted digits.length from the i (index) for the first iteration, the values would be 3 and 0 respectively, so you'd end up with 7000 for the first value if you passed in 756. Note also that in our return statement inside the map function, we wrap it back in a Number primitive to cast it back from a string.
Also, you didn't mention this, but I assume you'd rather not have numbers which equal 0 in your example. By calling filter on the final array before its returned, we can effectively make sure that only items which are not equal to 0 are returned. Thus, if you call breakup(756) you'll recieve [700, 50, 6], but breakup(706) will give you [700, 6] instead.
Instead of using split() to break out digits, I used a regex to tokenize the number string. This way, we can easily handle any trailing decimals by treating a digit followed by a decimal point and any further digits as a single token. This also makes it possible to handle digits as part of a larger string.
function splitNumber( number ) {
var parts = [];
var re = /(\d(?:\.\d*)?)/g;
while(next_part = re.exec(number)) {
// adjust place value
parts.forEach( function(element, index) {
parts[index] = 10 * element;
} );
parts.push( next_part[0] );
}
return parts.map(Number).filter(function(n) {return n !== 0});
}

Check/eliminate different row/columns in Backtracking function javascript

I have this code to solve a 3x3 sudoku (Only rows/columns are need to be checked, there can be 4 of the same numbers in one block, for example this is a good one:
123
231
312
)
I have the function fillsquare, with input an array [[1,2,0],[0,3,1],[3,0,2]] where the 0 need the be changed to the right number.
function fillsquare(square){
for (var a = 0; a<4; a++){
for (var b = 0; b<4; b++){
if (square[a][b] === 0){
// do the function to check whether I can enter the right number
}
else {
// ?????????????????????
}
}
}
}
According to my professor, it should be a recursive code, but I dont think this is recursive, anyways this base will work.
I still need to change the 0's to the number that fits in place.
I have a small clue how to do this with bruteforce/backtracking, but no code to achieve this.
enter 1 in the zero, if there isn't a one in the row or column, continue to the next zero. Else enter 2 and check again etc.
I hope you can help!
PS: My prof. gave me this psuedocode for checking etc.:
function fillSquare(square) {
find first 0 in square
if (there is no 0) {done!}
else {determine every value that can be put on the place with the zero
(check column and row) save them for example in a temprary row
for (every possible value) {
fillSquare(square with value filled in place)
}
}
}
I hope this is a bit clear, it is translated;)

Categories