LebGeeks

A community for technology geeks in Lebanon.

You are not logged in.

#1 April 16 2012

Joe
Member

[Exercise]Time converter

The goal of this exercise is to focus on code conciseness. If anyone feels like Code Golfing, be my guest, but I'm giving the exercise in such a way that's far from optimal for golf. More importantly, your focus should be on the expressivness of your algorithms, and work on this with as few lines of codes as possible.

The converter will convert between time measuring units. They are:

- seconds
- minutes
- hours
- days
- months
- years

The input is a string that follows this pattern:

<X> <unit1> in <unit2>?

//For instance:

1000000 days in years?
or 
33 hours in months?

Bonus points
Avoid giving floating numbers as an answer. You should instead decompose it in successively lower elements. In this aspect, "33 hours in months?" should not return "0.0458333" instead it should return "1 day 9 hours". I hope this is clear enough.

Conversion rates
The Gregorian Calendar is fundamentally stupid and wrong. It is littered with inconsistencies that would pollute the exercise. In order to avoid useless work, let's just focus on simple conversion rates, for the sake of this exercise:

1 year = 12 months = 360 days (I know...)
1 month = 30 days
1 day = 24h
1 hour = 60 minutes
1 minute = 60 secs.

Now, once you're done with your exercise, maybe you can tell me why we are still using this broken calendar system?

Offline

#2 April 16 2012

geek
Member

Re: [Exercise]Time converter

values = {1, 60, 60, 24, 30, 12};
names = {"second", "minute", "hour", "day", "month", "year"};
Do[values[[i]] *= values[[i - 1]], {i, 2, Length@values}]

(unit[#[[1]]] = #[[2]]) & /@ Partition[Riffle[names, values], 2];
(position[#[[1]]] = #[[2]]) & /@ Partition[Riffle[names, Range[Length@names]], 2];

h[ds_] := Module[
  {r},
  r = StringJoin[
    Reverse@MapIndexed[
      If[#1 > 0, ToString@#1 <> " " <> names[[#2]] <> If[#1 > 1, "s ", " "], ""] &,
      ds]
  ];
  If[r != "", StringDrop[r, -1], ""]
];

f[t_, u_: 0, z_: {}] := If[u == 0,
  z,
  f[Mod[t, values[[u]]], u - 1, Prepend[z, Quotient[t, values[[u]]]]]
];

g[s_] := With[
  {tokens = StringSplit[s]},
  f[ToExpression[tokens[[1]]] unit[StringDrop[tokens[[2]], -1]], position[StringDrop[tokens[[4]], -2]]]
];
is = {"1000000 days in years?", "33 hours in months?", "0 seconds in years?", "1 years in years?", "9876543210 seconds in years?"};
g /@ is
h /@ g /@ is

{{0, 0, 0, 10, 9, 2777}, {0, 0, 9, 1, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1}, {30, 13, 20, 11, 6, 317}}
{"2777 years 9 months 10 days", "1 day 9 hours", "", "1 year", "317 years 6 months 11 days 20 hours 13 minutes 30 seconds"}

Offline

Board footer