loading...

Daily Challenge #58 - Smelting Iron Ingots

thepracticaldev profile image dev.to staff ・1 min read

Minecraft has gotten to be a very popular game. No doubt many reading this have played it themselves or watched someone else. In Minecraft, collected ore must be smelted in a furnace to change the resource into a usable form.

Each ingot takes 11 seconds to produce. Steve has the following fuel options to add to the furnace:

Buckets of lava, each lasts 800 seconds
Blaze rod, each lasts 120 seconds
Coals, each lasts 80 seconds
Blocks of Wood, each lasts 15 seconds
Sticks, each lasts 1 second*

Write a function that calculates the minimum amount of fuel needed to produce a certain number of iron ingots.

Ruby: {:lava => 2, :blaze_rod => 1, :coal => 1, :wood => 0, :stick => 0}
JavaScript: {lava: 2, blazeRod: 1, coal: 1, wood: 0, stick: 0}

Good luck!~


Today's challenge comes from arwengu 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!

Discussion

pic
Editor guide
Collapse
dak425 profile image
Donald Feury

Time to Go smelting!

ingots.go

package ingots

const (
    lavaDuration     int = 800
    blazeRodDuration int = 120
    coalDuration     int = 80
    woodDuration     int = 15
)

// Requirements represents the differents types of fuel and in what amounts needed to complete the smelting job
type Requirements struct {
    Lava     int
    BlazeRod int
    Coal     int
    Wood     int
    Stick    int
}

// Fuel determines the fuel requirements to smelt the given number of ingots
func Fuel(ingots int) Requirements {
    if ingots <= 0 {
        return Requirements{0, 0, 0, 0, 0}
    }

    duration := ingots * 11

    return Requirements{
        Lava:     duration/lavaDuration + 1,
        BlazeRod: duration/blazeRodDuration + 1,
        Coal:     duration/coalDuration + 1,
        Wood:     duration/woodDuration + 1,
        Stick:    duration,
    }
}

ingots_test.go

package ingots

import "testing"

func TestFuel(t *testing.T) {
    testCases := []struct {
        description string
        input       int
        expected    Requirements
    }{
        {
            "a few ingots",
            2,
            Requirements{1, 1, 1, 2, 22},
        },
        {
            "wow that is alot of ingots",
            500,
            Requirements{7, 46, 69, 367, 5500},
        },
        {
            "negative amount of ingots",
            -5,
            Requirements{0, 0, 0, 0, 0},
        },
        {
            "no ingots",
            0,
            Requirements{0, 0, 0, 0, 0},
        },
    }

    for _, test := range testCases {
        if result := Fuel(test.input); result != test.expected {
            t.Fatalf("FAIL: %s - Fuel(%d): %+v - expected: %+v", test.description, test.input, result, test.expected)
        }
        t.Logf("PASS: %s", test.description)
    }
}

Collapse
mrsamse profile image
mrsamse

My solution in JavaScript:

const calcFuel = (n) => {
  const secsPerIngot = 11;
  let time = n * secsPerIngot;

  const lava = Math.floor(time / 800);
  time = time - lava * 800;
  const blazeRod = Math.floor(time / 120);
  time = time - blazeRod * 120;
  const coal = Math.floor(time / 80);
  time = time - coal * 80;
  const wood = Math.floor(time / 15);
  time =  time - wood * 15;
  const stick = Math.floor(time / 1);

  return {lava, blazeRod, coal, wood, stick};
};
Collapse
chrisachard profile image
Chris Achard

I think I interpreted this correctly (though "minimum number" could mean a few different things here...)

Here's my solution using javascript's reduce:

const fuel = ingots => {
  let need = ingots * 11

  const types = [
    {name: 'lava', sec: 800},
    {name: 'blazeRod', sec: 120},
    {name: 'coal', sec: 80},
    {name: 'wood', sec: 15},
    {name: 'stick', sec: 1},
  ]

  return types.reduce((r, v) => {
    r[v.name] = Math.floor(need / v.sec)
    need = need - (r[v.name] * v.sec)
    return r
  }, {})
}

And you can watch me solve it here! youtu.be/wtA4CKbZipA

Collapse
suchafoka profile image
Suchafoka

Python

def fuel(a):
    a = a * 11
    i= 0
    tab = []
    t1 = [800,120,80,15,1]
    t2 = ['lava','blazeRod','coal','wood','stick']
    while a > 0:
        if  a > t1[i]:
            if a % t1[i] == 0:
                tab.append([t2[i],  a // t1[i]])
                a = 0
            else:
                tab.append([t2[i], a // t1[i]])
                a = a % t1[i]
        else:
            tab.append([t2[i],  0])
        i+=1
    if i < 5:
        while i <5:
            tab.append([t2[i],  0])
            i+=1
    return tab
Collapse
charlie117 profile image
Charlie Fuentes

The challenge was a little bit ambiguous about the requirement. If I understand correctly, is asking about at least how many resources of each fuel you require to try to smelt iron ingots.
With this, I wrote the following solution in JavaScript

const calculateFuelForIrons = ironCubesQty => {
  const FUEL_DURATION = {
    lava: 800,
    blazeRod: 120,
    coal: 80,
    wood: 15,
    stick: 1
  };

  const smeltingTime = ironCubesQty * 11;

  return Object.keys(FUEL_DURATION).reduce((result, key) => {
    const newResult = {
      ...result,
      [key]: Math.floor(smeltingTime / FUEL_DURATION[key])
    };

    return { ...newResult };
  }, {});
};

console.log(calculateFuelForIrons(10));
console.log(calculateFuelForIrons(110));
console.log(calculateFuelForIrons(11000));
console.log(calculateFuelForIrons(0));
Collapse
craigmc08 profile image
Craig McIlwrath

I'm not sure if I'm correctly interpreting the problem, but:

data Fuels a = Fuels { lava :: a
                   , blazeRod :: a
                   , coal :: a
                   , wood :: a
                   , stick :: a
                   } deriving (Show, Eq)

defFuels :: (Integral a) => Fuels a
defFuels = Fuels 0 0 0 0 0

minFuel :: (Integral a) => a -> Fuels a
minFuel items = defFuels{lava = ceiling $ fromIntegral items * 11 / 800}

The minimum amount of fuel to cook n items will always be only lava buckets...

My other interpretation was the amount of fuel to get the exact correct smelting time. I did work on a solution for that, but it felt very verbose with a lot of repeated code to work with my Fuels type. I'm pretty new to Haskell, so I'm not sure if this is the best thing to use in this situation. I did think about using a map, but then I would have to deal with Maybes when looking up items from the map. Any advice or reccomendations would be appreciated.

Collapse
cgty_ky profile image
Cagatay Kaya
const furnace = (ingot = 0) => {
  var fuel = [
    { type: "lava", duration: 800, count: 0 },
    { type: "blazeRod", duration: 120, count: 0 },
    { type: "coal", duration: 80, count: 0 },
    { type: "wood", duration: 15, count: 0 },
    { type: "stick", duration: 1, count: 0 }
  ];

  let pTime = ingot * 11;
  if (pTime <= 0 || isNaN(pTime)) {
    console.log("No fuel consumption is necessary");
  } else {
    fuel.map(item => {
      item.count = Math.floor(pTime / item.duration);
      pTime = pTime - item.count * item.duration;
    });
    fuel.forEach(item => console.log(`${item.type}: ${item.count}`));
  }
};
Collapse
dbarwikowski profile image
Daniel Barwikowski

link to codewars?