2
\$\begingroup\$

I wrote two functions for determining leap years. ("Kabisat" means "leap year" in Indonesia.)

def kabisat? y
  return false if y%4!=0   
  return true if y%100!=0  
  y%400==0                 
end

def kabisat_2? y
  return true if y%400==0   
  return false if y%100==0  
  y%4==0                    
end 

require 'date';

(1..Date.today.year).each { |y|
  puts y if kabisat?(y)!=kabisat_2?(y)
}

Is it correct? And it is possible to write a shorter one?

\$\endgroup\$
5
  • 4
    \$\begingroup\$ Why not use the built-in Date#leap? method? In any event, your kabisat_1 function is broken. It'll return true for, say, 2013, because it's not divisible by 100. But 2013 certainly isn't a leap year. \$\endgroup\$
    – Flambino
    Commented Mar 14, 2013 at 10:06
  • \$\begingroup\$ no it is not? kabisat? 2013 == false \$\endgroup\$
    – Kokizzu
    Commented Mar 14, 2013 at 10:30
  • \$\begingroup\$ Yes, your method checks y%4!=0 first, so it'll return the right thing. But reversing the checks is suspect. The logic is that "if a year is divisible by 100, it's not a leap year". But that does not mean, that every year that isn't divisible automatically is a leap year. I.e. the check against 100 can only can only tell you if something's not a leap year; it can't tell you if it is. \$\endgroup\$
    – Flambino
    Commented Mar 14, 2013 at 10:55
  • \$\begingroup\$ You should test it with some corner cases, e.g. 1900, 2000, 2004. \$\endgroup\$
    – Sjoerd
    Commented Mar 14, 2013 at 11:32
  • 1
    \$\begingroup\$ Why don't u google? rosettacode.org/wiki/Leap_year#Ruby \$\endgroup\$
    – Nakilon
    Commented Mar 14, 2013 at 23:34

1 Answer 1

3
\$\begingroup\$

Some notes:

  • I assume that, for some reason, you want to write your own function/method instead of the existing Date#leap? that @Flambino linked above.
  • kabisat? We all love our mother tongue, but in computing English is the lingua franca, specially when you share your code with people around the world. It's a nice word to learn, though :-)
  • This is a personal advice, not all Ruby programmers agree: don't use inline returns. Use the good old full-fledged conditionals, it's much more clear. In general, use expressions instead of statements.

Let's see the standard algorithm. Ok, I'll just translate it to Ruby (if I felt fancy I'd even add Integer#divisible_by?(n) for a fully declarative code):

def is_leap_year?(year)
  if year % 400 == 0 
    true
  elsif year % 100 == 0
    false
  elsif year % 4 == 0
    true
  else
    false
  end
end

Too verbose? use boolean logic:

def is_leap_year?(year)
  (year % 400 == 0) || (year % 100 != 0 && year % 4 == 0)
end
\$\endgroup\$
1
  • \$\begingroup\$ i like the boolean logic :3 \$\endgroup\$
    – Kokizzu
    Commented Mar 14, 2013 at 12:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.