DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #260 - Subtract the Sum

Complete the function which get an input number n such that n >= 10 and n < 10000, then:

Sum all the digits of n.
Subtract the sum from n, and it is your new n.
If the new n is in the list below return the associated fruit, otherwise return back to task 1.

Example
n = 325
sum = 3+2+5 = 10
n = 325-10 = 315 (not in the list)
sum = 3+1+5 = 9
n = 315-9 = 306 (not in the list)
sum = 3+0+6 = 9
n =306-9 = 297 (not in the list)
...
. ...until you find the first n in the list below.

Here are all possible values of n:

1-kiwi
2-pear
3-kiwi
4-banana
5-melon
6-banana
7-melon
8-pineapple
9-apple
10-pineapple
11-cucumber
12-pineapple
13-cucumber
14-orange
15-grape
16-orange
17-grape
18-apple
19-grape
20-cherry
21-pear
22-cherry
23-pear
24-kiwi
25-banana
26-kiwi
27-apple
28-melon
29-banana
30-melon
31-pineapple
32-melon
33-pineapple
34-cucumber
35-orange
36-apple
37-orange
38-grape
39-orange
40-grape
41-cherry
42-pear
43-cherry
44-pear
45-apple
46-pear
47-kiwi
48-banana
49-kiwi
50-banana
51-melon
52-pineapple
53-melon
54-apple
55-cucumber
56-pineapple
57-cucumber
58-orange
59-cucumber
60-orange
61-grape
62-cherry
63-apple
64-cherry
65-pear
66-cherry
67-pear
68-kiwi
69-pear
70-kiwi
71-banana
72-apple
73-banana
74-melon
75-pineapple
76-melon
77-pineapple
78-cucumber
79-pineapple
80-cucumber
81-apple
82-grape
83-orange
84-grape
85-cherry
86-grape
87-cherry
88-pear
89-cherry
90-apple
91-kiwi
92-banana
93-kiwi
94-banana
95-melon
96-banana
97-melon
98-pineapple
99-apple
100-pineapple

Tests:
SubtractSum(10)
SubtractSum(1204)

Good luck!


This challenge comes from aryan-firouzian on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Oldest comments (17)

Collapse
 
loriick profile image
Travailleur Lorick

why I always get apple 😅 ?

Collapse
 
aminnairi profile image
Amin • Edited

Go

EDIT: just realized this challenge was a trap, but leaving the (wrong) solution here for people wanting to try out Go (it's awesome, try it).

Commands for initializing the project.

$ mkdir $GOPATH/src/fruits
$ cd $GOPATH/src/fruits
$ touch fruits.go

The source-code.

// Set of utilities for manipulating fruits.
package fruits

// Find a fruit based on its index.
func FindFromInteger(integer uint16) string {
    if integer < 9 {
        switch (integer) {
        case 1:
            return "kiwi"

        case 2:
            return "pear"

        case 3:
            return "kiwi"

        case 4:
            return "banana"

        case 5:
            return "melon"

        case 6:
            return "banana"

        case 7:
            return "melon"

        case 8:
            return "pineapple"
        }
    }

    return "apple"
}

Commands for the unit tests.

$ touch fruits_test.go

The source-code for unit tests.

package fruits_test

import "testing"
import "fruits"
import "fmt"

func TestFindFromInteger(t *testing.T) {
    var valuesExpectations map[uint16]string = map[uint16]string{
        0: "apple",
        1: "kiwi",
        2: "pear",
        3: "kiwi",
        4: "banana",
        5: "melon",
        6: "banana",
        7: "melon",
        8: "pineapple",
        9: "apple",
        10: "apple",
        100: "apple",
        1_000: "apple",
        325: "apple",
        10_000: "apple",
    }

    for value, expectation := range valuesExpectations {
        var result string = fruits.FindFromInteger(value)

        if result != expectation {
            t.Errorf("Expected fruits.FindFromInteger(%d) to equal %s but got %s.", value, expectation, result)
        }
    }
}

func BenchmarkFindFromInteger(b *testing.B) {
    for index := 0; index < b.N; index++ {
        fruits.FindFromInteger(10_000)
    }
}

func ExampleFindFromInteger() {
    fmt.Printf("Fruit for index %d is %q.\n", 15, "apple")
    // Output: Fruit for index 15 is "apple".
}

Commands for the tests, benchmark and coverage.

$ go test -cover -bench .
goos: linux
goarch: amd64
pkg: fruits
BenchmarkFindFromInteger-4      482598516                2.58 ns/op
PASS
coverage: 100.0% of statements
ok      fruits  1.500s
Collapse
 
saswat01 profile image
saswat

Python grill:

alt code

Collapse
 
pbouillon profile image
Pierre Bouillon • Edited

My version, in C# 😄

    public static string GetMatchingWordFor(int number)
    {
        var nValues = GetDictionaryFromRawString(RawValues);

        while (!nValues.ContainsKey(number))
        {
            number -= number.ToString()
                .Select(digit => int.Parse(digit.ToString()))
                .Aggregate(0, (acc, x) => acc + x);
        }

        return nValues[number];
    }

The helper function to convert the raw list into a usable dictionary:

    public static Dictionary<int, string> GetDictionaryFromRawString(string raw)
    {
        return raw.Split("\n")
            .Select(str =>
                str.Trim()
                    .Split("-"))
            .ToDictionary(
                row => int.Parse(row[0]),
                row => row[1]);
    }
Collapse
 
vidit1999 profile image
Vidit Sarkar

Here is a solution,

return "apple";
Collapse
 
vidit1999 profile image
Vidit Sarkar

And here is a recursive Python solution,

fruits = [
    "kiwi",
    "pear",
    ....
    "melon",
    "pineapple",
    "apple",
    "pineapple"
]

def SubtractSum(number : int) -> str:
    temp = number - sum(map(int ,str(number)))
    if(1 <= temp <= 100):
        return fruits[temp-1]
    return SubtractSum(temp)
Collapse
 
willsmart profile image
willsmart • Edited

A quick JS one:

First up, set up the base fruit mapping by splitting that string:

const
  inputFruitMappingString = `1-kiwi
2-pear
...other entries...
99-apple
100-pineapple`,
  baseFruitMapping = Object.fromEntries(
    inputFruitMappingString.split('\n').map(line => line.split('-'))
  )

The fruit-fetching-function itself:

function fruitForIndex(i) {
  return baseFruitMapping[i] ??
    fruitForIndex(
      [...String(i)].reduce((acc, digit) => acc - digit, i)
    );
}

The guts of that is: [...String(i)].reduce((acc, digit) => acc - digit, i)
Breaking that up:

  • String(i): i is a number so to split it into characters, render it into a standard decimal string
  • [...String(i)]: Easy way to split the string into chars
  • [...String(i)].reduce((acc, digit) => acc - digit, i): The reduce function is passed the number itself as its initial value and then goes through the array of digits, subtracting each from the running total.

Bit of sanity checking...

// Debug version of the function
function fruitForIndex(i) {
  console.log(i), 
  return baseFruitMapping[i] ?? fruitForIndex([...String(i)].reduce((acc, digit) => acc - digit, i));
}

> fruitForIndex(1)
1
< "kiwi"

> fruitForIndex(100)
100
< "pineapple"

> fruitForIndex(101)
101
99
< "apple"

> fruitForIndex(200)
200
198
180
171
162
153
144
135
126
117
108
99
< "apple"


Note that it's worth making sure you have a modern JS engine
Caniuse for Object.fromEntries
Caniuse for ??

Collapse
 
alxtrnr profile image
Alex Turner • Edited

I think this might be called a naive solution...

import random

def number_fruit():
    fruit_list = []
    fruit_dict = {
        1:'kiwi',
        2:'pear',
        3:'kiwi',
        4:'banana',
        5:'melon',
        6:'banana',
        7:'melon',
        8:'pineapple',
        9:'apple',
        10:'pineapple',
        11:'cucumber',
        12:'pineapple',
        13:'cucumber',
        14:'orange',
        15:'grape',
        16:'orange',
        17:'grape',
        18:'apple',
        19:'grape',
        20:'cherry',
        21:'pear',
        22:'cherry',
        23:'pear',
        24:'kiwi',
        25:'banana',
        26:'kiwi',
        27:'apple',
        28:'melon',
        29:'banana',
        30:'melon',
        31:'pineapple',
        32:'melon',
        33:'pineapple',
        34:'cucumber',
        35:'orange',
        36:'apple',
        37:'orange',
        38:'grape',
        39:'orange',
        40:'grape',
        41:'cherry',
        42:'pear',
        43:'cherry',
        44:'pear',
        45:'apple',
        46:'pear',
        47:'kiwi',
        48:'banana',
        49:'kiwi',
        50:'banana',
        51:'melon',
        52:'pineapple',
        53:'melon',
        54:'apple',
        55:'cucumber',
        56:'pineapple',
        57:'cucumber',
        58:'orange',
        59:'cucumber',
        60:'orange',
        61:'grape',
        62:'cherry',
        63:'apple',
        64:'cherry',
        65:'pear',
        66:'cherry',
        67:'pear',
        68:'kiwi',
        69:'pear',
        70:'kiwi',
        71:'banana',
        72:'apple',
        73:'banana',
        74:'melon',
        75:'pineapple',
        76:'melon',
        77:'pineapple',
        78:'cucumber',
        79:'pineapple',
        80:'cucumber',
        81:'apple',
        82:'grape',
        83:'orange',
        84:'grape',
        85:'cherry',
        86:'grape',
        87:'cherry',
        88:'pear',
        89:'cherry',
        90:'apple',
        91:'kiwi',
        92:'banana',
        93:'kiwi',
        94:'banana',
        95:'melon',
        96:'banana',
        97:'melon',
        98:'pineapple',
        99:'apple',
        100:'pineapple'        
    }

    num_int = random.randint(10,10000)
    num_str = str(num_int)
    num_list = list(num_str)    
    num_list_int = []


    for x in num_list:
        xint = int(x)
        num_list_int.append(xint)

    sum_num_int_list = sum(num_list_int)   
    new_n = num_int - sum_num_int_list

    if new_n in fruit_dict:
        print(new_n,'=',fruit_dict[new_n])
    else: 
        number_fruit()

number_fruit()

...and neither do I understand recursion (maximum recursion depth exceeded while calling a Python object) and why it always comes up apple.

Collapse
 
mistrikushal profile image
Kushal

Here is Ruby solution,

FRUITS = {
  1 => 'kiwi',
   ...
  100 => 'pineapple'
}

def substract_sum(num)
  if num >= 10 && num < 10000
    sum_of_digits = num.to_s.chars.map(&:to_i).inject(:+)
    if FRUITS.keys.include?(sum_of_digits)
      puts FRUITS[sum_of_digits]
    else
      puts "#{sum_of_digits} (not in the list)"  
    end
  else
    puts 'Enter valid number'  
  end
end

substract_sum(10)
substract_sum(1204)
Collapse
 
peter279k profile image
peter279k

Here is my simple solution to find the fruit name with PHP:

function subtractSum($n) {
  // fruit name "apple"
  $fruitArray = ["kiwi",
"pear",
"kiwi",
"banana",
"melon",
"banana",
"melon",
"pineapple",
"apple",
"pineapple",
"cucumber",
"pineapple",
"cucumber",
"orange",
"grape",
"orange",
"grape",
"apple",
"grape",
"cherry",
"pear",
"cherry",
"pear",
"kiwi",
"banana",
"kiwi",
"apple",
"melon",
"banana",
"melon",
"pineapple",
"melon",
"pineapple",
"cucumber",
"orange",
"apple",
"orange",
"grape",
"orange",
"grape",
"cherry",
"pear",
"cherry",
"pear",
"apple",
"pear",
"kiwi",
"banana",
"kiwi",
"banana",
"melon",
"pineapple",
"melon",
"apple",
"cucumber",
"pineapple",
"cucumber",
"orange",
"cucumber",
"orange",
"grape",
"cherry",
"apple",
"cherry",
"pear",
"cherry",
"pear",
"kiwi",
"pear",
"kiwi",
"banana",
"apple",
"banana",
"melon",
"pineapple",
"melon",
"pineapple",
"cucumber",
"pineapple",
"cucumber",
"apple",
"grape",
"orange",
"grape",
"cherry",
"grape",
"cherry",
"pear",
"cherry",
"apple",
"kiwi",
"banana",
"kiwi",
"banana",
"melon",
"banana",
"melon",
"pineapple",
"apple",
"pineapple",];

  $number = $n;
  while(true) {
      $str = (string)$number;
      $sum = 0;
      for($index=0; $index<strlen($str); $index++) {
          $sum += (int)$str[$index];
      }

      $number = $number - $sum;

      if ($number <= 99) {
          break;
      }

  }

  return  $fruitArray[$number-1];
}
Collapse
 
boris profile image
Boris Quiroz • Edited

Some python-that-can-be-improved:

elements = [
        "1-kiwi",
        "2-pear",
        "3-kiwi",
        "4-banana",
        "5-melon",
        "6-banana",
        "7-melon",
        "8-pineapple",
        "9-apple",
        "10-pineapple",
        "...",
        "100-pineapple"
        ]

def substractSum(n):
    if 10 <= n <= 10000:
        sum_n = 0
        for digit in str(n):
            sum_n += int(digit)

        result = n - sum_n

        while result > 100:
            for digit in str(n):
                sum_n += int(digit)
            result = n - sum_n

        print(n, result, elements[result-1])
    else:
        print("{}: Use value between 10 and 10000".format(n))

substractSum(9)
substractSum(10)
substractSum(31)
substractSum(110)
substractSum(111)
substractSum(325)
substractSum(1204)
substractSum(1316)
substractSum(2888)
substractSum(10000)
substractSum(10001)

Output of the above:

❯ python 260.py
9: Use value between 10 and 10000
10 9 9-apple
31 27 27-apple
110 100 100-pineapple
111 99 99-apple
325 95 95-melon
1204 98 98-pineapple
1316 95 95-melon
2888 80 80-cucumber
10000 100 100-pineapple
10001: Use value between 10 and 10000