1
\$\begingroup\$

Task: Get array of random integer (less than 10) numbers and random sequence of mathematical operations (multiplication and addition) which, when applied, will give a even number

Example: genOddSeq(4) -> [[6, 6, 6, 9], ['+', '*', '*']] (6 + 6 * 6 * 9 = 330)

Code:

function genOddSeq(count) {
  let getRandomInt = (min, max) => Math.floor(Math.random() * (Math.ceil(max) - Math.ceil(min))) + Math.ceil(min)
  let result = []
  let operations = []
  let numbersComp = 0;

  for (let i = 0; i < count; i++) {
    result.push(getRandomInt(1, 10))
  }

  for (let i = 0; i < count - 1; i++) {
    operations.push(Math.random() > 0.5 ? '+' : '*')
  }

  numbersComp += operations[0] == '+' ? result[0] + result[1] : result[0] * result[1]

  for (let i = 1; i < count - 1; i++) {
    numbersComp = operations[i] == '+' ? numbersComp + result[i + 1] : numbersComp * result[i + 1]
  }

  if (numbersComp % 2 != 0) {
    result[getRandomInt(0, count)] += 1
  } 

  return [result, operations]
}
\$\endgroup\$
2
\$\begingroup\$

Your function name is strange. You wanted to get a sequence of random numbers and operations whose result is an even number. But you named your function genOddSeq. Also, avoid abbreviations. Write code for the human, not the machine.

Instead of using an empty array and a loop to fill that array, consider using Array(), Array.fill() and array.map(). For example, creating an array of 10 random values from 0 to 1 would look like:

const tenRandomDecimals = Array(10).fill().map(Math.random)

You can do the same for the operations.

Now instead of hard-coding the logic of the operation selection inside a ternary, consider using a key-value pair where the key is + and * and the values are functions that accept two numbers which do the actual operation. When you generate an array of random + and *, just use them to get the actual function in the key-value pair.

if (numbersComp % 2 != 0) {
  result[getRandomInt(0, count)] += 1
}

This bit of logic is strange. Do you really need to get a random value? Or can you just use one from a known location, like the first number?

Last but not least, tests. It's always good practice to start with tests. Even other code review posts include a minimal form of test to verify the code is working.

Anyways, here's how I'd implement it. A bit longer, but there's no surprises. There's no state held, no variables to keep track of. Also using const both as a signal and a guarantee that the value will not change during runtime.

const operationFunctions = {
  '+': (a, b) => a + b,
  '*': (a, b) => a * b,
}
const operationKeys = Object.keys(operationFunctions)
const getRandomInteger = (min, max) => Math.floor(Math.random() * (Math.ceil(max) - Math.ceil(min))) + Math.ceil(min)
const getRandomOperationKey = () => operationKeys[Math.floor(Math.random() * operationKeys.length)]
const range = size => Array(size).fill().map((v, i) => i)

const getEvenResultSequence = count => {
  const firstNumber = getRandomInteger(1, 10)
  const numbers = range(count - 1).map(() => getRandomInteger(1, 10))
  const operations = range(count - 1).map(getRandomOperationKey)
  const result = operations.reduce((c, v, i) => operationFunctions[v](c, numbers[i]), firstNumber)
  const adjustedFirstNumber = result % 2 ? firstNumber + 1 : firstNumber

  return [[adjustedFirstNumber, ...numbers], operations]
}

console.log(getEvenResultSequence(4))
console.log(getEvenResultSequence(4))
console.log(getEvenResultSequence(4))
console.log(getEvenResultSequence(4))
console.log(getEvenResultSequence(4))

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.