Picking 2 values at random from the project array

My task is to develop a program that adds together 2 randomly selected values.

The program should include a function with a list of numbers ranging from 1 to 9. Two random values are to be retrieved from this list using array.splice().

Once the two random values are chosen, the program will calculate their sum (addition) to obtain a total value of randomvalue1 + randomvalue2 = totalvalue;

THE TWIST! When selecting the 2 random values, they cannot be the same (e.g., 5+5, 3+3, 2+2, etc., are considered invalid).

ANOTHER TWIST! The program must also ensure that the random values do not repeat consecutively. This means that randomvalue1 and randomvalue2 should not have the same value in two consecutive selections.

I've been provided with the following code, which unfortunately does not address the repetition of the same values multiple times in succession:

function makeRandom(list) {
 function getRandomIndex() {
     return Math.floor(Math.random() * list.length);
 }

let index1 = getRandomIndex(),
    index2 = getRandomIndex();

while (index1 === index2) index2 = getRandomIndex();

return list[index1] + '+' + list[index2];
}
console.log(makeRandom([1, 2, 3, 4, 5, 6, 7, 8, 9]));

Answer №1

To retrieve values from an array, you can iterate through the indices until a different index is found.

function makeRandom(list) {
    function getRandomIndex() {
        return Math.floor(Math.random() * list.length);
    }
    
    let index1 = getRandomIndex(),
        index2 = getRandomIndex();

    while (index1 === index2) index2 = getRandomIndex();

    return list[index1] + '+' + list[index2];
}

console.log(makeRandom([1, 2, 3, 4, 5, 6, 7, 8, 9]));

An alternative method involves excluding specific indices during the selection process.

function makeRandom(list, exclude = []) {
    function getRandomIndex() {
        return Math.floor(Math.random() * list.length);
    }
    function getFreeIndex() {
        let index;

        if (exclude.length >= list.length) return;

        do index = getRandomIndex();
        while (exclude.includes(index))

        exclude.push(index);
        return index;
    }
    
    return getFreeIndex() + '+' + getFreeIndex();
}

console.log(makeRandom([1, 2, 3, 4, 5, 6, 7, 8, 9], [2, 3]));

Answer №2

Given Assumptions

  1. An array of numbers is provided as input

  2. Every call to makeRandom will randomly select two numbers from the array and output their sum

  3. Subsequent calls to makeRandom should not reuse any number (id) already used

     list = [1,1,2,3,4,5];
     // The number 1 can be used twice but only in different function calls
     // The numbers 2,3,4,5 can only be used once
    
     list = [1,1];
     // This won't work since 1 == 1
    

Javascript Code

var list    = [1,2,3,4,5,6,7,8,9];    // Initial list provided
var usable  = list.slice(0);          // Copy of initial list that will be altered by makeRandom
function makeRandom(){
    // Checking feasibility...
    let counts = {};                                       // Object to count unique numbers
    for (var i = 0; i < usable.length; i++) {
        counts[usable[i]] = 1 + (counts[usable[i]] || 0);  // Fill counts with unique numbers from array
    }
    if(Object.keys(counts).length < 2){                    // Ensure at least two unique numbers exist
        console.log("List is too short!");                 // Log an error if less than two unique numbers
        return false;                                      // Exit function if condition not met
    }


    // Generating random numbers and calculating sum...
    let id = Math.floor(Math.random() * usable.length)   // Randomly select an id from usable numbers
    let a  = usable[id];                                 // Set first number
    usable.splice(id, 1);                                // Remove 1st number from usable numbers
    
    let b;
    while(true){                                         // Loop until numbers are different
        id = Math.floor(Math.random() * usable.length);  // Randomly select an id from usable numbers
        b  = usable[id];                                 // Set second number
        if(a !== b)break;                                // Check if first number isn't identical to the second one
    }
    usable.splice(id, 1);                                // Remove 2nd number from usable numbers
//  console.log(a + " + " + b + " = " + (a+b));          // Optional log statement
    return a+b;                                          // Return sum of 1st and 2nd numbers
}

Note: To enhance understanding, the while loop is shown in full; it could be simplified using do...while(...):

    let b;
    do b = list[Math.floor(Math.random() * list.length)];  // Set second number
    while(a==b)                                            // Re-set second number if a == b OR if b was used previously in makeRandom

Example Scenario

var list    = [1,2,3,4,5,6,7,8,9];
var usable  = list.slice(0);
function makeRandom(){
    let counts = {};
    for (var i = 0; i < usable.length; i++) {
        counts[usable[i]] = 1 + (counts[usable[i]] || 0);
    }
    if(Object.keys(counts).length < 2){
        console.log("List is too short!");
        return false;
    }
    let id = Math.floor(Math.random() * usable.length)
    let a  = usable[id];
    usable.splice(id, 1);
    let b;
    while(true){
        id = Math.floor(Math.random() * usable.length);
        b  = usable[id];
        if(a !== b)break;
    }
    usable.splice(id, 1);
    console.log(a + " + " + b + " = " + (a+b));
    return a+b;
}
// Multiple function calls
makeRandom();
makeRandom();
makeRandom();
makeRandom();
makeRandom();
makeRandom();

// Altering the seed lists
var list    = [1,1,1,1,1,9];
var usable  = list.slice(0);

// Additional function calls
makeRandom();
makeRandom();
makeRandom();

Output Example

__Example 1__
list = [1,2,3,4,5,6,7,8,9]; // Sample list used

                // console.log           return
> makeRandom(); // 4 + 2 = 6             6
> makeRandom(); // 1 + 8 = 9             9
> makeRandom(); // 9 + 3 = 12            12
> makeRandom(); // 6 + 7 = 13            13
> makeRandom(); // List is too short!    false
> makeRandom(); // List is too short!    false

__Example 2__
list = [1,1,1,1,1,9]; // Sample list used

                // console.log           return
> makeRandom(); // 1 + 9 = 10            10
> makeRandom(); // List is too short!    false
> makeRandom(); // List is too short!    false

An Alternative Approach

Considering the changes made to your question...

It's unclear whether numbers can only be used once or if they cannot be used consecutively.

list = [1,2,3,4,5];
                 // Choose from      // Chosen
> makeRandom();  // 1, 2, 3, 4, 5    // 1, 4
> makeRandom();  // 2, 3, 5          // 2, 3
> makeRandom();  // 1, 4, 5          // 1, 5

If that's the case, then the following alternative method may be more helpful

var list = [1,2,3,4,5,6,7,8,9];    // Your seed list
var used = [];           // Last used pair of numbers
function makeRandom(){
    // Check it's possible...
    let counts = {};                                       // Create object to count unique numbers
    for (var i = 0; i < list.length; i++) {
        counts[list[i]] = 1 + (counts[list[i]] || 0);  // Iterate array and fill counts
    }
    if(Object.keys(counts).length < 4){                    // Check there are at least four unique numbers: any less and we'll end up in an infinite loop on the second call of makeRandom
        console.log("List is too short!");                 // Log error if <2
        return false;                                      // Exit function if <2
    }


    // Get random numbers and output sum...
    let a;
    do a = list[Math.floor(Math.random() * list.length)];  // Set first number
    while(used.includes(a))                                // Reset first number if a was used in the last call to makeRandom
    let b;
    do b = list[Math.floor(Math.random() * list.length)];  // Set second number
    while(a==b || used.includes(b))                        // Re-set second number if a == b OR if b was used in the last call to makeRandom

    used = [a, b];                                         // Set last used numbers
    console.log(a + " + " + b + " = " + (a+b));            // Log for debugging if required
    return a+b;                                            // Return sum of 1st and 2nd numbers
}

// Make several calls to function
makeRandom();
makeRandom();
makeRandom();
makeRandom();
makeRandom();
makeRandom();

// Change the seed lists
var list    = [1,2,3,4];

// Make several calls to function
// With only 4 numbers, once the first pair is selected (e.g. 1 & 3), the pattern cycles between 1,3 -> 2,4 -> 1,3 -> 2,4
makeRandom();
makeRandom();
makeRandom();

Answer №3

Revised Solution

After revising the requirements of the question, it became clear that the original solution provided below is not suitable for the task at hand. This updated version offers a solution that aligns with the new specifications.

We have devised a function that selects values randomly from a fixed array while ensuring that none of the n most recently used items are selected. For example, if we set n to 4 and provide an array [1, 2, 3, 4, 5, 6, 7, 8, 9], the function will return a unique value on each call until all four previously selected values have been exhausted. Subsequent calls will continue this pattern without any repeated values among these four selections. The fifth selection may include any unused values, introducing randomness into the process.

const noRepeatRandom = (n, arr) => {
  // TODO: handle error case when n >= arr.length
  let available = [...arr]
  let used = []
  return () => {
    const nextIdx = Math.floor(Math.random() * available.length)
    const next = available[nextIdx]
    used.push(next)
    available.splice(nextIdx, 1)
    if (used.length >= n) {
      available.push(used.shift())
    }
    return next
  }  
}
const myRandom = noRepeatRandom(4, [1, 2, 3, 4, 5, 6, 7, 8, 9])

// display results of multiple calls to `myRandom()`
console.log(...Array.from({length: 30}, myRandom))

We maintain two lists - one containing available but unseen values, and the other storing recently used values that cannot be reused immediately (available and used). Initially, both lists populate with elements, but once used reaches n length, we begin rotating elements between the two lists.

An important note regarding error handling: the code should validate input parameters such as n and the array length. If n >= arr.length, the function should terminate gracefully. Addressing this issue remains an exercise for the reader. Additionally, setting n == arr.length - 1 leads to an infinite loop cycling through the same set of arr.length items due to limited choices available.


Original Implementation

This preceding solution diverges from the specified requirements after further elucidation. While still beneficial, it fails to meet the criteria outlined.

I opted for a method involving a partial shuffle of the array. The snippet provided showcases a recursive adaptation of the Fisher-Yates shuffle, truncated once n elements have been picked. Notably, this operation does not alter the initial array.

To enhance this functionality, I extended the approach by creating pickTwo using currying techniques and applying the value 2.

const partialShuffle = (n) => (xs, i = Math.floor(Math.random() * xs.length)) =>
  n <= 0 || n > xs.length || xs.length == 0
    ? []
    : [xs[i], ...partialShuffle(n - 1)([...xs.slice(0, i), ...xs.slice(i + 1)])]

const pickTwo = partialShuffle(2)

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]

for (let i = 0; i < 5; i++) {
  console.log(...pickTwo(arr))
}

console.log('Initial Array Untouched:', ...arr)
.as-console-wrapper {max-height: 100% !important; top: 0}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Troubleshooting a glitch with passing a variable to a PHP script using AJAX

Explanation of the page functionality: When the quiz php page loads, a user can create a score using a function in quiz.js. This score is then stored in a variable score within quiz.js Once the score is generated, the user must click a button to move on ...

The app.get() function seems to be inactive and not triggering in the Express application

I am currently exploring the MEAN stack and experimenting with implementing express. I've encountered a peculiar issue where I keep receiving a 404 error when trying to access a specific path that I have configured for the app object to manage. Oddly ...

What are the steps to execute a filter operation on a table by utilizing two select box values with jQuery?

I have a challenge with two dropdown menus. One contains names and the other subjects, along with a table displaying information in three columns: name, subject, and marks. I would like to implement a filter based on the selections in these two dropdowns. ...

How can I protect my jQuery script from being accessed by "FIREBUG"?

I was tasked with creating a jQuery script as follows: function DeleteFile(_FileID) { //ajax method to delete the file } The FileID is stored in the 'rel' attribute of the list. However, when I call "DeleteFile" from Firebug using the fileId ...

Modify the parent scope variable within an Angular directive that contains an isolated scope

Here is a directive implementation: <some-directive key="123"></some-directive> This directive code looks like this: angular.module('app').directive('someDirective', ['someFactory', '$compile', '$ ...

Currying in React - Understanding the Handler

Can anyone explain to me how this currying works in the example provided? I understand the name argument, but how does the event work in this scenario? <TextField placeholder="Name" InputLabelProps={{ shrink: true, ...

There seems to be an issue with PHP associative arrays when using a foreach loop

I'm encountering issues with a form designed to submit details for creating an order and an invoice. One of the variables in the form is an associative array structured like this. Hello, thank you for your assistance. After using print_r($_POST), I r ...

Is there a way for me to ensure that the value copied to my clipboard is accurate?

When I click a button in my process, it automatically copies an email address. How can I verify that the copied value matches my expectations? I was attempting to paste it into the terminal to check, but if there is a more efficient method to do this, I wo ...

Is there a reason for the inability to deactivate JavaScript in GhostDriver/PhantomJSDriver?

Is there a way to turn off JavaScript in PhantomJSDriver for only one page? I found this link that says it's not possible because it will make the whole GhostDriver unusable. Could you explain why this happens in a simple way, like I'm just 5 ye ...

Expanding the dropdown menu depending on the selection of the radio button

I am looking to implement a feature where the drop-down option is displayed or hidden based on the selection of a radio button in AngularJS. If the "Overall Company" radio button is selected, then the drop-down element should not be shown. If the "Demogra ...

Challenges regarding OAuth2 and the angular-auth2-oidc Library - Utilizing PKCE Code Flow

As a newcomer to OAuth2 and the angular-auth2-oidc library, I may make some beginner mistakes, so please bear with me. MY GOAL: I aim to have a user click on the login link on the home page, be directed to the provider's site to log in, and then retu ...

Querying Parse Server for objectId information

Within my web app that utilizes the Parse Server Javascript SDK, I have implemented the following query. While the console log accurately displays the retrieved information, the objectId field appears as "undefined." var query = new Parse.Query("myClass") ...

Is it possible to generate a triangular attachment below a div element?

My designer sent me a unique design and I'm wondering if it's possible to replicate using HTML, CSS, or JavaScript? https://i.stack.imgur.com/spB71.png I believe it can be done with CSS by creating a separate div positioned absolutely under the ...

Insert a fresh item into the current JSON structure

I am facing an issue with a dropdown in my code. Here is how it looks: <input id="tripFrom" type="text" angular-select2="{type:'typeahead',placeholder:'- Select -'}" select-typeahead-params="{removeTripId:currentTrip.custome ...

Transferring an array from a Node.js server to another array on an HTML webpage

app.get('/reservedDeskNames', function(req, res) { connection.query( 'SELECT DeskName FROM desks WHERE status = ?',["Booked"], function(err, rows){ if(err) { throw err; } else ...

Issues arise when attempting to retrieve information in NextJS from a local API

One of my coworkers has created a backend application using Spring Boot. Strangely, I can only access the API when both our computers are connected to the same hotspot. If I try to access the other computer's API and port through a browser or Postman, ...

What order should jquery files be included in?

Today I ran into an issue while trying to add datepicker() to my page. After downloading jqueryui, I added the scripts in the following order: <script type="text/javascript" src="js/jquery.js"></script> <script src="js/superfish.js">< ...

Populate several input boxes with data derived from a single input field

I am facing an issue with three textboxes in my project. When I type something in the first textbox, the value is sent to state.jsp and displayed using out.println(firsttextboxvalue); on the response ID of the second textbox. However, I want to populate th ...

What is the best way to evaluate two objects with varying data types?

Is it possible to compare two objects with different data types? var a = { sort: 7, start: "0"} var b = { sort: "7", start: "0"} I thought they should be equal, but when I try using JSON.stringify(a) === JSON.stringify(b), it returns false. ...

Tips for consolidating all functions into a single file for ReactJS inheritance:

I'm curious about something. In Angular JS, we have the ability to create a global service file that can be inherited by every component. This allows us to use the functions written in the global service file within each respective component. Is ther ...