Problem of the Day
A new programming or logic puzzle every Mon-Fri

Bill Split

Today's problem is an easy but useful one. Given a list of bills, print out how much each roommate owes. There will exist some cases where your currency does not support the denomination when split. In that case one roommate will have to pay more than another. For example:

bill_split(2, [11, 15, 11.01])
18.50
18.51

Permalink: http://problemotd.com/problem/bill-split/

Comments:

  • Andreas - 10 years, 4 months ago

    done in Scala (there is probably a shorter way, but this is what I came up with first)

    def billSplit(count: Int, bills: List[Double]) {
      val overall = bills.map(_ * 100).sum.toInt
      val atLeast = overall / count
      var rest = overall % count
    
      (1 to count) foreach { x =>
        if (rest == 0) println(atLeast / 100.0)
        else {
          println((atLeast + 1) / 100.0)
          rest -= 1
        }
      }
    }
    

    reply permalink

  • Nick Krichevsky - 10 years, 4 months ago

    from math import floor
    
    def splitBill(n,*args):
        r = float(sum(args))/n
        if r*100==round(r*100):
            return [r for i in range(n)]    
        else:
            f = round((r*100-floor(r*100))/100,2)
            print f
            l = [floor(r*100)/100 for i in range(n-1)]
            l.append(floor((r+f)*100)/100)
            return l
    

    reply permalink

  • bumbleguppy - 10 years, 4 months ago

    This was one of those seems-simple-enough-OH-MY-GOD-WHAT'S-HAPPENING problems. Floating point numbers are craaaaaaaazy, at least in javascript. Also, I didn't feel right dumping the remainder on one payer if there were more than 2 people and the remainder was more than 1.

    function billSplit(numPayers, billsArr){
        var total = billsArr.reduce(function(a,b){return a + b;}) * 100; //multiply by 100 to mitigate floating point "issues"
        var eachAmt = Math.floor(total / numPayers); //rough total per payer
        var leftoverAmt = total - (eachAmt * numPayers); // remainder that doesn't divide in evenly
        var returnArray = [];  
    
        /**        
        if the remainder after dividing the total by the number of payers 
        is greater than 1, theres no reason you can't share the load and 
        add 1 currency unit to more than one random sucker
        **/
        var unluckyArray = new Array(numPayers);
        var i = leftoverAmt;
        var randomSucker = 0;
        while(i){
            randomSucker = Math.floor(Math.random() * numPayers);
            if(!unluckyArray[randomSucker]){ //test if this guy has already been shafted
                unluckyArray[randomSucker] = true; //shaft him
                i--;
            }
        }
    
        for(var i = 0; i < numPayers; i++){
            if(unluckyArray[i]){
                returnArray[i] = (eachAmt + 1) / 100; //divide by 100 to get final floating point value
            }else{
                returnArray[i] = eachAmt / 100; //divide by 100 to get final floating point value
            }
        }
    
        // makes pretty $trings
        function formatUSD(num){
            var remainder = Math.floor((num * 100) % 100);
            num = '$' + Math.floor(num);
            switch(remainder){
                case 0:
                    return num + '.00';
                    break;
                case num < 10:
                    return num + '.0' + remainder;
                    break;
                default:
                    return num + '.' + remainder;
            }
        }
    
        return returnArray.map(formatUSD);
    }
    

    reply permalink

Content curated by @MaxBurstein