4

Link to challenge

You're going on a trip with some students and it's up to you to keep track of how much money each Student has. A student is defined like this:

class Student {
  constructor(name, fives, tens, twenties) {
    this.name = name;
    this.fives = fives;
    this.tens = tens;
    this.twenties = twenties;
  }
}

As you can tell, each Student has some fives, tens, and twenties. Your job is to return the name of the student with the most money. If every student has the same amount, then return "all".

Notes:

Each student will have a unique name

There will always be a clear winner: either one person has the most, or everyone has the same amount

If there is only one student, then that student has the most money


I've tried this:

function mostMoney(students) {
  //get array of totals
  let array = [];
  students.forEach((value, index) => {
     let total = ((5 * value.fives) + (10 * value.tens) + (20 * value.twenties));
     array.push([total, value.name]);
  });
  //sort array of totals
  array = array.sort((a, b) => b[0] - a[0]);
  console.log('array****', array);
  //check if all totals are equal - if they are, return 'all'
  if (array.every((el, i, array) => (el)[0]) === array[0][0]) {
    return 'all'; 
  }
  else {
    return array[0][1];
  }
}

What doesn't make sense to me is that when I console.log('array****', array); in codewars it looks like:

array**** [ [ 50, 'Eric' ],
  [ 40, 'Andy' ],
  [ 40, 'Stephen' ],
  [ 40, 'Phil' ],
  [ 30, 'David' ] ]
array**** [ [ 50, 'Eric' ],
  [ 40, 'Andy' ],
  [ 40, 'Stephen' ],
  [ 40, 'Phil' ],
  [ 30, 'Cameron' ],
  [ 30, 'Geoff' ],
  [ 30, 'David' ] ]
array**** [ [ 40, 'Andy' ] ]
array**** [ [ 40, 'Stephen' ] ]
array**** [ [ 30, 'Cameron' ], [ 30, 'Geoff' ] ]

Why does it look like that? I would think that after sorting, my console.log('array***', array) should just look like:

array**** [ [ 50, 'Eric' ],
  [ 40, 'Andy' ],
  [ 40, 'Stephen' ],
  [ 40, 'Phil' ],
  [ 30, 'Cameron' ],
  [ 30, 'Geoff' ],
  [ 30, 'David' ] ]

When I initially console.log(students), it looks like an array:

[ Student { name: 'Andy', fives: 0, tens: 0, twenties: 2 },
  Student { name: 'Stephen', fives: 0, tens: 4, twenties: 0 },
  Student { name: 'Eric', fives: 8, tens: 1, twenties: 0 },
  Student { name: 'David', fives: 2, tens: 0, twenties: 1 },
  Student { name: 'Phil', fives: 0, tens: 2, twenties: 1 } ]

So I'm trying to collect all of the totals in an array with my forEach loop, and then sorting that array after looping - what's wrong with that logic?

enter image description here

Community
  • 1
  • 1
HappyHands31
  • 4,001
  • 17
  • 59
  • 109
  • You mean you have multiple console logs? – aksappy Nov 15 '19 at 21:49
  • it appears that way, even though I'm only doing one console.log in my code: https://i.imgur.com/mFRlI3O.png – HappyHands31 Nov 15 '19 at 21:50
  • 1
    possibly your `mostMoney` function is called multiple times in your tests?, hence the multiple console logs? – C.OG Nov 15 '19 at 21:56
  • The code is being run against a series of tests, so the console is going to log multiple datasets. – zzzzBov Nov 15 '19 at 21:57
  • @c_ogoo oh okay - that helps clear up some confusion. So then the problem is still just with my `.every()`, I'm assuming - it's not returning true when all values are the same. – HappyHands31 Nov 15 '19 at 21:57
  • I tried commenting out the tests, but it is still running tests. And I have no idea why! – aksappy Nov 15 '19 at 21:59
  • I know nothing about CodeWars, but in general, `console.log` may reflect the current state of an object/array, rather than the state it was in at the time of logging. See https://stackoverflow.com/questions/49838597/weird-array-behaviour-in-javascript – Heretic Monkey Nov 15 '19 at 22:00

2 Answers2

1

Working solution : )

function mostMoney(students) {
  let array = [];
  if (students.length === 1) {
     return students[0].name;
  }
  students.forEach((value, index) => {
     let total = ((5 * value.fives) + (10 * value.tens) + (20 * value.twenties));
     array.push([total, value.name]);
  });
  array = array.sort((a, b) => b[0] - a[0]);
  if (array.every((el, i, array) => el[0] === array[0][0])) {
    return 'all'; 
  }
  else {
    return array[0][1];
  }
}

There was in fact a problem with my .every - I was doing (el)[0]) instead of el[0], and then I also wasn't properly checking for when there was only one student passed into mostMoney.

Thanks all for shedding light on the console.log issue. Codewars was console.logging multiple times because, as you all mentioned, it's running multiple tests.

HappyHands31
  • 4,001
  • 17
  • 59
  • 109
1

I can suggest as solution:

  function mostMoney(students) {
     //deep copy of argument
     let input = [...students];
     // sort students by total descending
     let sum = st => st.fives * 5 + st.tens * 10 + st.twenties * 20;
     let comparator = (st1,st2) => sum(st2) - sum(st1);
     input.sort(comparator);     
     // result
     //just compare the first two students
     if(input.length >=2 && sum(input[0]) == sum(input[1])){
      return 'all';
     }
     else{
      return input[0].name;
     }
  }
zouari
  • 967
  • 1
  • 6
  • 13