Numbers from inside a string without regex? - javascript

I'm making a bot for a gaming chatroom with some friends, but I've hit an impasse. Is there a reliable way to get numbers from inside a string of text that won't completely break an inexperienced script kiddy's brain? Here's the best I've been able to come up with so far, variables simplified slightly for illustration's sake:
var k = [0];
function dieRoll(m,n) {
for(i = 0; i < m; i++) {
k[i] = Math.floor(Math.random()*n)+1;
}
}
var m = text[5];
var n = text[7];
if (text === 'roll '+m+'d'+n) {
dieRoll(m,n)
console.log(k);
}
The biggest problem as-is is that it's limited to single-digit input.
EDIT: Looping through the text looking for integers is exactly the kind of thing I'm looking for. I don't have much experience with programming, so I probably tend to end up with overly complicated and confusing messes of spaghetti code that would embarrass anyone remotely professional. As for the format of the input I'm looking for, "roll [number of dice]d[highest number on the dice]". For anyone who doesn't know, it's the notation most tabletop rpgs use. For example, "roll 2d6" for two normal six-sided dice.
EDIT: It's not that I'm necessarily against regex, I just want to be able to understand what's going on, so that if and when I need to edit or reuse the code it I can do so without going completely insane.
EDIT: Thank you all very much! split() seems to be exactly what I was looking for! It'll probably take some trial and error, but I think I'll be able to get her working how she's supposed to this weekend (Yes I call my bots 'she').

Basically, you need to look at the format of the input you're using, and identify certain facts about it. Here are the assumptions I've taken based on your question.
1) The "roll" command comes first followed by a space, and
2) After the command, you are provided with dice information in the form xdy.
Here's something that should work given those constraints:
function getRollParameters(inputCommand) {
var inputWords = inputCommand.split(' '); //Split our input around the space, into an array containing the text before and after the space as two separate elements.
var diceInfo = inputWords[1]; //Store the second element as "diceInfo"
var diceDetails = diceInfo.split('d'); //Split this diceInfo into two sections, that before and after the "d" - ie, the number of dice, and the sides.
//assign each part of the dicedetails to an appropriate variable
var dice = diceDetails[0];
var sides = diceDetails[1];
//return our two pieces of information as a convenient object.
return {
"dice": dice,
"sides": sides
};
}
//a couple of demonstrations
console.log(getRollParameters("roll 5d8"));
console.log(getRollParameters("roll 126d2"));
Effectively, we're first splitting the string into the "command", and the "arguments" - the information we want. Then, we split our arguments up using the "d" as a midpoint. That gives us two numbers - the one before and the one after the d. Then we assign those values to variables, and can use them however we like.
This obviously won't deal with more creative or flexible inputs, and isn't tested beyond the examples shown but it should be a decent starting point.

Related

Bitboard Javascript - How to identify the exactly piece/position is attacking the king

I don't have too much knowledge about bitboards and bit operations and I got some examples of bitboard chess engines from Github.
And I like to know if anyone can help me with a problem.
How can I identify the exact piece that is attacking the king?
I got an example in the isKingInCheck function from position.js that just identifies when the king is attacked (even identifies if the piece is pawn, or bishop, etc.), but I need to know exactly the piece (position) that is attacking the king.
I believe that would be possible creating a generic attack mask function, like the function below. The problem is that I don't know how I get each piece (and its position during the game) individually from the pre-made bitboards, declared in the position.js file.
Chess.Position.makePawnAttackMask = function(color, pawns) {
var white = (color === Chess.PieceColor.WHITE);
var attacks1 = pawns.dup().and_not(Chess.Bitboard.FILES[0]).shiftLeft(white ? 7 : -9);
var attacks2 = pawns.dup().and_not(Chess.Bitboard.FILES[Chess.LAST_FILE]).shiftLeft(white ? 9 : -7);
return attacks1.or(attacks2);
};
Anyone know how can I achieve this?
I think the most efficient way to find the checking pieces would be to find them at the same time as you generate the legal moves. That would require some refactoring and could be a bit complicated.
One easier way would be to use a reworked copy of the isAttacked function by generating the attack masks for each piece starting from the king's position.
For example, if you send the king's bitboard to the makePawnAttackMask function with the king's color and you apply a logical and between the mask and the opposite player's pawns, you'll get a bitboard containing the checking pawn. You can then use the function extractLowestBitPosition or getLowestBitPosition to find the square of the attacking pawn if it exists. Make sure the bitboard is not empty before trying to extract the least significant bit's position :
Chess.Position.prototype.getCheckingPieces = function(color) {
var checkingPieces = [];
var opponent = Chess.getOtherPieceColor(color);
var king = this.getPieceColorBitboard(Chess.Piece.KING, color);
var pawnAttack = Chess.Position.makePawnAttackMask(color, king);
pawnAttack = pawnAttack.and(This.getPieceColorBitboard(Chess.Piece.PAWN, opponent));
if (!pawnAttack.isEmpty()) {
checkingPieces.push(pawnAttack.extractLowestBitPosition());
if (checkingPieces.length > 1) {
return checkingPieces;
}
}
// ... evaluate attacks from the 4 other piece types
return checkingPieces;
}
If you'll be finding checking pieces using only legal chess positions, positions that could happen in an actual game, then you could stop once you've found 2 checking pieces as it's impossible for 3 pieces to check the king at once.
I believe you could also quit looking for pieces of one type once you've found one in the mask, except for the queen. I think it is right that in a legal chess position a king can't be attacked by 2 of the same piece type at once except for 2 queens since a pawn capture/promotion to a queen can give check and at the same time discover a queen attack.

Generating random number that will not repeat between surveys in Qualtrics using javascript

A disclaimer: I'm not familiar with Javascript. I've merely cobbled together a basic understanding of what I need to do for this task from Stack Overflow and other resources. My apologies if something below is unclear.
My problem: I need to generate a random number between 0 and 8,764, using Javascript, that will not repeat itself between Qualtrics survey responses.
Currently, I've found code to create an array that contains all numbers between 0 and 8,764, shuffles the array, and pops the last number off the end of the array.
It then adds embedded data to Qualtrics with that popped number, and I can then pipe the embedded data into a Qualtrics question to display it to my survey respondent. See below:
Qualtrics.SurveyEngine.addOnReady(function()
{
for (var i = 0, ar = []; i < 8; i++) {
ar[i] = i;
}
ar.sort(function () {
return Math.random() - 0.5;
});
var randomnumber = ar.pop();
Qualtrics.SurveyEngine.addEmbeddedData("randomnumber", randomnumber);
});
However, as far as I can tell, this Javascript code "resets" itself between survey responses, meaning it will re-create and re-shuffle the array each time a new respondent enters the survey. I'd like to find a way to make it so that it will be impossible for a new respondent to see the same popped "randomnumber" as a previous respondent. So, if the first survey respondent saw a 1, then the next survey respondent could see any number besides a 1 (let's say they see a 100 instead), and the next respondent could see any number except a 1 or a 100, etc etc.
I think it's possible to use embedded data in Javascript code and manipulate it (see here). It seems like there might be a way to access the randomnumber embedded data and write Javascript code to not remove any numbers from the array that match one of the previously popped randomnumbers. I lack the technical knowledge to execute this, if it's even the best way to accomplish the task.
Any and all help appreciated!
You can do what you want with Advanced Randomization in Qualtrics.
Set up a multiple choice question with your numbers 0 through 8,764 as the choices. Then use Advanced Randomization to select a random subset of 1 from all the numbers and click "Evenly Present" (Evenly Present is what tells Qualtrics to use every number before reusing any). Use JavaScript to hide the multiple choice question:
$(this.questionId).hide();
Now you can pipe your unique random number into a subsequent question. For example:
${q://QID1/ChoiceGroup/DisplayedChoices}

Is there a built-in way to match ranges of values against ranges of values in JavaScript?

Let's say I have a value somewhere in a list items, whose value is a range from 3-10.
Then let's say I search using a range from say 5-15.
Since the lower end of the search range (5) falls within the range of the entry in the list (3-10), then it should match.
To do this I have to check if either range value in the search falls between the range values of the entry, and vice-verse.
While I have a working function for this, I was wondering if there is a common pattern or built-in way to do this kind of "range matrix" filtering in JavaScript. I don't even know if there is some actual nomenclature for this sort of thing.
Expected behavior: https://repl.it/Jz6c/0
Perhaps this is more of a Code Review question than a Stack Overflow question, but since we're here...
Based on your repl.it demo, it looks like you are asking if there is a simpler way to write this code:
var matchesRange = function(min, max, value) {
return value >= min && value <= max;
};
var matchesRangeMatrix = function(searchRange, targetRange) {
return matchesRange(searchRange.min, searchRange.max, targetRange.min) ||
matchesRange(searchRange.min, searchRange.max, targetRange.max) ||
matchesRange(targetRange.min, targetRange.max, searchRange.min) ||
matchesRange(targetRange.min, targetRange.max, searchRange.max);
};
where you call matchesRangeMatrix() with two object arguments, each of which has a min and max property.
This code makes a total of eight comparisons (four calls to matchesRange with two comparisons each).
You can do the whole thing with only two comparisons. Let's take out the matrix nomenclature, since that seems to make it sound more complicated than it is. Instead, how about a function called rangesOverlap():
function rangesOverlap( one, two ) {
return one.min < two.max && two.min < one.max;
}
That's all you need! Try this updated version of your repl.it and compare the results with your original.
If you're wondering how something so simple could work, I invite you to read this Hacker News discussion where I and a few other people debated this very topic. (I'm "Stratoscope" over there, but in particular look for a comment by "barrkel" about a third of the way down the page that lists a truth table for this problem.)
The context of that discussion was whether two appointments conflict or not. For example, appointments from 1-2pm and 2-3pm would not conflict even though the first one ends at the same time the second one begins. If your definition of overlapping ranges is different, so 1-2 and 2-3 would be considered to overlap, you should be able to do this by using <= instead of <:
function rangesOverlap( one, two ) {
return one.min <= two.max && two.min <= one.max;
}
But fair warning, I have not tested this version of the code.
Note that this isn't anything specific to JavaScript. The same question and the same solutions would apply to pretty much any programming language.

Find if a string line is nested or is a child of another line

I'm looking to write a small parser for some kind of files, and one of the things I have to accomplish is to find if a line is inside another one, defining this with indentation (spaces or tabs).
Example:
This is the main line
This is a nested or child line
I'm trying to establish this by reading the first character position in the line and comparing it with the previous one with something like this:
var str = ' hello';
str.indexOf(str.match(/\S|$/).shift());
I'm sure this is not the best way and it looks horrible, also I have another issues to address, like checking if the indentation is made by spaces (2 or 4), or tabs, or passing/maintaining an state of the previous line (object).
Also, lines can be infinitely nested and of course I'm looking more for a nice and performant algorithm (or idea), or pattern rather than a simple check that I think is relatively easy to do but error prone. I'm sure it is already solve by people who works with parsers and compilers.
Edit:
str.search(/\S/);
#Oriol proposal looks much better
This is generally the kind of thing you write a parser for, rather than purely relying on regex. If the nesting determines the depth, then you have two things to solve: 1) find the depth for an arbitrary line, and 2) iterate through the set of lines and track, for each line, which preceding line has a lower depth value.
The first is trivial if you are familiar with the RegExp functions in Javascript:
function getDepth(line) {
// find leading white space
var ws = str.match(/^(\s+)/);
// no leading white space?
if (ws === null) return 0;
// leading white space -> count the white space symbols.
// obviously this goes wrong for mixed spaces and tabs, and that's on you.
return ws[0].split('').length;
}
The second part is less trivial, and so you have several options. You could iterate through all the lines, and track the list of line numbers, pushing onto the list as you go deeper and popping from the list as you go back up, or you can build a simple tree structure (which is generally far better because it lets you expand its functionality much more easily) using standard tree building approached.
function buildTree(lines, depths) {
if (!depths) {
var depths = lines.map(e => getDepth);
return buildTree(lines, depths);
}
var root = new Node();
for(var pos=0, end=lines.length; pos<end; pos++) {
var line = lines[pos];
var depth = depths[pos];
root.insert(line, depth);
}
}
With a simple Node object, of course
var Node = function(text, depth) {
this.children = [];
this.line = text.replace(/^\s+/,'');
this.depth = depth;
}
Node.prototype = {
insert: function(text, depth) {
// this is where you become responsible: we need to insert
// a new node inside of this one if the depths indicate that
// is what should happen, but you're on the hook for determining
// what you want to have happen if the indentation was weird, like
// a line at depth 12 after a line at depth 2, or vice versa.
}
}

Unbalanced binary tree not functioning properly. Node.Js

So I was solving a problem for class involving binary search and the algorithm I implemented to solve it worked fine but my hunch is that a slight gamble would be more effective given the parameters of the problem
The fictional town of HollyBroke, Fl is made up of a 30 x 30 block grid. The streets are named after the presidents of the United States and the avenues are numbered numerically. The infamous two-word arsonist is holding the town hostage. He selects a house every Saturday for destruction by fire and taunts the police department by challenging them to guess the location for each week’s crime. He will answer up 10 guesses with either a “yes”or a “no” answer during his very brief phone call right before he strikes the match. (He won’t stay on the line so the call can’t be trace.)
The city wants you to develop a program to provide a quick response when this notorious criminal calls.
The answer to that was easy enough to create an algorithm for but I thought a median-1/median+1 gamble would be more effective. My hunch is that more often than not I will arrive at the conclusion with one extra question to go allowing me to either ask a binary search question about the arsonist or if the game allowed it I would show up with police before the end of the call. If I don't outright solve it beforehand I would have a very small space to search after it was completed, like three or four blocks right next to each other,
This is my code for the "gambling" binary search.
`var array = [{"a":30,"b":30,"c":0}]
function findLower(input) {
var half = Math.floor(input/2);
if(0 == input%2)
return (half-1);
else
return (half);
};
function findUpper(input) {
var half = Math.floor(input/2);
if(input%2 == 0)
return (half+1);
else
return (half+1);
}
for (var i = 0; i <= 9; i++){
for (var z = array.length - 1; z >= 0; z--) {
if (array[z].c = i){
if (array[z].a>array[z].b)
array.push({"a":findLower(array[z].a),"b":array[z].b,"c":array[z].c + 1},{"a":findUpper(array[z].a),"b":array[z].b,"c":array[z].c + 1})
else
array.push({"a":array[z].a,"b":findLower(array[z].b),"c":array[z].c + 1},{"a":array[z].a,"b":findUpper(array[z].b),"c":array[z].c + 1})
}
};
}
console.log(array.length);`
Its coming up with an absurd array length given that it should be 2^10 +2^9 + 2^8 ..... = 2047
The program is coming up with an array length of 19683
And some of the arrays should most certainly not be 30*14 at node level 10 I'm sure the algorithm was set up properly. I've walked it through two levels by pen and paper and it seems like it should work properly.
Found it.
if (array[z].c = i){
should be
if (array[z].c == i){
its a conditional statement not declaring them equal
Also I was wrong. You only have about a 40% chance of successfully locating the house in 10 guesses.

Categories