Help with leap year programing

Discussion in 'Ruby' started by HB, Sep 1, 2007.

  1. HB

    HB Guest

    Hi, All,

    I am a beginner on programming now reading books by Chris Pine: Learn
    to Program.
    On chapter 6, I got same assignment. I guess that is a classic one.

    I have tried to use what I have learned so far: The loop.

    My code is as below. i have run several test without finding any
    problem.

    Can you help to have a look and throw some light on any possible
    improvement? Thanks.

    ____________________

    puts 'starting year:'
    s = gets.chop
    puts 'ending year:'
    e = gets.chop

    if s.to_i > e.to_i
    puts 'ending year should be bigger than staring year'
    else
    puts 'leap year between ' + s + ' and '+ e + ' as below:'
    end

    while s.to_i < e.to_i

    while ( (s.to_i % 4 == 0 and s.to_i % 100 != 0) or (s.to_i % 100 ==
    0 and s.to_i % 400 == 0 ))
    puts s
    s = s.to_i + 1
    end
    s = s.to_i + 1
    end
    puts 'all done'


    On Nov 7, 2006, at 12:15 PM, Shiloh Madsen wrote:


    > So, I'm trying to go through the Teach Yourself Programming book by
    > Pragmatic Press and I am encountering a few hurdles. The chapter I am
    > working on now is asking me to create a program which will ask for a
    > start and end year and then calculate all leap years in that range.
    > The logic behind leap years (for those who need a refresher) is all
    > years divisible by for are leap years EXCEPT those that are divisible
    > by 100 UNLESS they are also divisible by 400. I am somewhat at a loss
    > for how to handle the logic for this...finding all numbers that are
    > divisible by 4 and removing those divisible by 100 is easy. Its adding
    > in that third condition which adds some of the removed numbers back
    > into the "true" group that I am having trouble with...or maybe I am
    > just not wrapping my mind around the problem well
    > enough...suggestions?



    The key point of all the methods proposed in this thread is: deal
    with the years divisible by 400 first, the years divisible by 100
    second, and the years divisible by 4 last of all.

    Regards, Morton
    HB, Sep 1, 2007
    #1
    1. Advertising

  2. On 01.09.2007 16:33, HB wrote:
    > I am a beginner on programming now reading books by Chris Pine: Learn
    > to Program.
    > On chapter 6, I got same assignment. I guess that is a classic one.
    >
    > I have tried to use what I have learned so far: The loop.
    >
    > My code is as below. i have run several test without finding any
    > problem.
    >
    > Can you help to have a look and throw some light on any possible
    > improvement? Thanks.


    The fist thing I'd change is to remove all the #to_i's. You should
    convert to integer just once, namely after reading user input. If you
    use Integer() for the conversion, then you also get automatic error
    checking, i.e., if the user enters "foo" no calculations will be done
    but he will see an error message instead.

    Next, I am not sure what you are trying to achieve. As far as I can see
    there is no condition on the "puts s" but your print statement seems to
    indicate that you are interested in leap years only. If you want to
    print leap years only then you need to somehow put a condition around
    that output statement.

    Normally you would need just a single loop as far as I understand the
    problem and what you are trying to do. So you could get rid of one of them.

    I would also move the leap year output code inside the if-else. The
    code will likely work the way it is as well because if s>e the body of
    the while loop will never be executed. But from a control flow point of
    view the code becomes clearer when you nest the "activity" (leap year
    calculation and output in this case) in the proper branch of the
    conditional statement.

    > ____________________
    >
    > puts 'starting year:'
    > s = gets.chop
    > puts 'ending year:'
    > e = gets.chop
    >
    > if s.to_i > e.to_i
    > puts 'ending year should be bigger than staring year'
    > else
    > puts 'leap year between ' + s + ' and '+ e + ' as below:'
    > end
    >
    > while s.to_i < e.to_i
    >
    > while ( (s.to_i % 4 == 0 and s.to_i % 100 != 0) or (s.to_i % 100 ==
    > 0 and s.to_i % 400 == 0 ))
    > puts s
    > s = s.to_i + 1
    > end
    > s = s.to_i + 1
    > end
    > puts 'all done'


    Kind regards

    robert
    Robert Klemme, Sep 1, 2007
    #2
    1. Advertising

  3. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    * HB:

    > On chapter 6, I got same assignment. I guess that is a classic one.


    So here is a nonclassic solution to this classic problem :)

    If s % 4 differs from 0 we start with a year that cannot be a leap year.
    If this occurs add 4 - (s % 4) to skip to the next year that is a leap
    year unless century rules happen to apply. Now only every fourth year
    needs to be considered. A year that can be divided by four is a leap
    year under the condition that it can be divided by 400 or cannot be
    divided by 100.

    puts 'starting year:'
    s = gets.chomp.to_i
    puts 'ending year:'
    e = gets.chomp.to_i

    if s > e
    puts 'ending year should be bigger than staring year'
    else
    puts "leap year between #{s} and #{e} as below:"
    end

    s += 4 - (s % 4) if s % 4 != 0

    while s <= e
    puts s if (s % 400 == 0 or s % 100 != 0)
    s += 4
    end
    puts 'all done'

    Josef 'Jupp' Schugt
    - --
    Blog available at http://www.mynetcologne.de/~nc-schugtjo/blog/
    PGP key with id 6CC6574F available at http://wwwkeys.de.pgp.net/
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.7 (GNU/Linux)
    Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

    iD8DBQFG2ZkSrhv7B2zGV08RAmuVAJ4xCwywVTVlXg2S3kUvtibQcynnmgCg2hHD
    Mpa+a5kp4DdFSqLqMa+FDQQ=
    =T/yP
    -----END PGP SIGNATURE-----
    Josef 'Jupp' Schugt, Sep 1, 2007
    #3
  4. HB

    Hu Yoi Guest

    HB wrote:
    > Hi, All,
    >
    > I am a beginner on programming now reading books by Chris Pine: Learn
    > to Program.
    > On chapter 6, I got same assignment. I guess that is a classic one.
    >
    > I have tried to use what I have learned so far: The loop.
    >
    > My code is as below. i have run several test without finding any
    > problem.
    >
    > Can you help to have a look and throw some light on any possible
    > improvement? Thanks.
    >


    I think it's easier to use Date#leap? for this question.

    puts 'Starting year:'
    start = gets.chop
    puts 'Ending year:'
    ending = gets.chop
    if start.to_i > ending.to_i
    puts 'Ending year should be bigger than staring year'
    else
    puts 'Leap year between ' + start + ' and '+ ending + ' as below:'
    while start.to_i <= ending.to_i
    if Date.new(start.to_i).leap?
    puts start
    end
    start = start.to_i + 1
    end
    end
    puts 'all done'


    Yoi
    --
    Posted via http://www.ruby-forum.com/.
    Hu Yoi, Sep 2, 2007
    #4
  5. HB

    HB Guest

    On Sep 3, 12:24 am, Hu Yoi <> wrote:
    > HB wrote:
    > > Hi, All,

    >
    > > I am a beginner on programming now reading books by Chris Pine: Learn
    > > to Program.
    > > On chapter 6, I got same assignment. I guess that is a classic one.

    >
    > > I have tried to use what I have learned so far: The loop.

    >
    > > My code is as below. i have run several test without finding any
    > > problem.

    >
    > > Can you help to have a look and throw some light on any possible
    > > improvement? Thanks.

    >
    > I think it's easier to use Date#leap? for this question.
    >
    > puts 'Starting year:'
    > start = gets.chop
    > puts 'Ending year:'
    > ending = gets.chop
    > if start.to_i > ending.to_i
    > puts 'Ending year should be bigger than staring year'
    > else
    > puts 'Leap year between ' + start + ' and '+ ending + ' as below:'
    > while start.to_i <= ending.to_i
    > if Date.new(start.to_i).leap?
    > puts start
    > end
    > start = start.to_i + 1
    > end
    > end
    > puts 'all done'
    >
    > Yoi
    > --
    > Posted viahttp://www.ruby-forum.com/.


    Thanks to all!
    I have a lot to learn and it is fun!
    HB, Sep 8, 2007
    #5
  6. HB

    7stud -- Guest

    HB wrote:
    > Hi, All,
    >
    > I am a beginner on programming now reading books by Chris Pine: Learn
    > to Program.
    >
    > ...
    >
    > while ( (s.to_i % 4 == 0 and s.to_i % 100 != 0) or (s.to_i % 100 ==
    > 0 and s.to_i % 400 == 0 ))
    >
    > The key point of all the methods proposed in this thread is: deal
    > with the years divisible by 400 first, the years divisible by 100
    > second, and the years divisible by 4 last of all.
    >
    > Regards, Morton



    Your complex conditional can be expressed more clearly with a series of
    if statements:

    start = 2000
    finish = 2200

    year = start

    while year <= finish

    is_leap =
    if year % 400 == 0
    true
    elsif year % 100 == 0
    false
    else
    year % 4 == 0
    end

    if is_leap: puts year
    end

    year += 1
    end



    Or you can use each() on a Range for your loop, and a case statement
    inside the loop:

    start = 2000
    finish = 2200

    user_range = start..finish

    user_range.each do |year|

    is_leap =
    case
    when year % 400 == 0
    true
    when year % 100 == 0
    false
    else
    year % 4 == 0
    end

    if is_leap: puts year
    end

    year += 1
    end
    --
    Posted via http://www.ruby-forum.com/.
    7stud --, Sep 9, 2007
    #6
  7. I have a little modification, I included the minutes in a year.


    #!/usr/bin/ruby

    puts "please enter starting year:"
    STDOUT.flush
    starting = gets

    puts "please enter end_year:"
    STDOUT.flush
    end_year = gets

    year = starting.to_i

    while year <= end_year.to_i

    leapyear =
    if year % 400 == 0
    true
    elsif year % 100 == 0
    false
    else
    year % 4 == 0
    end


    if leapyear: puts "#{year}-> This year is a leapyear and #{366*60*24}
    minutes"
    else
    puts "#{year}-> Not a leapyear #{365*60*24} minutes"
    end
    year += 1
    end


    Good day,
    Bernie Loriaga
    --
    Posted via http://www.ruby-forum.com/.
    Bernie Loriaga, Oct 16, 2008
    #7
  8. [Note: parts of this message were removed to make it a legal post.]

    :) That is what I am talking about... I just ran it from my e-mail... much
    better for the assignment. You are greatly improving, by the way!
    Warmest Regards,

    Victor H. Goff III
    Voice (218) 206-2470



    On Thu, Oct 16, 2008 at 2:14 AM, Bernie Loriaga <> wrote:

    > I have a little modification, I included the minutes in a year.
    >
    >
    > #!/usr/bin/ruby
    >
    > puts "please enter starting year:"
    > STDOUT.flush
    > starting = gets
    >
    > puts "please enter end_year:"
    > STDOUT.flush
    > end_year = gets
    >
    > year = starting.to_i
    >
    > while year <= end_year.to_i
    >
    > leapyear =
    > if year % 400 == 0
    > true
    > elsif year % 100 == 0
    > false
    > else
    > year % 4 == 0
    > end
    >
    >
    > if leapyear: puts "#{year}-> This year is a leapyear and #{366*60*24}
    > minutes"
    > else
    > puts "#{year}-> Not a leapyear #{365*60*24} minutes"
    > end
    > year += 1
    > end
    >
    >
    > Good day,
    > Bernie Loriaga
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >
    Victor H. Goff III, Oct 16, 2008
    #8
  9. Thanks Vic,
    I just copy the code and modify it a little,is it mean that I'm
    improving?
    Right now,I'm reading some ruby book.I want to improve my ruby skill.

    Take care & Good day,
    Bernie Loriaga
    --
    Posted via http://www.ruby-forum.com/.
    Bernie Loriaga, Oct 16, 2008
    #9
  10. HB

    Hh Rg Guest

    The problem comes from a beginner´s tutorial. Using methods like .leap?
    of course work just fine. However, a beginner is not familiar with them.
    This a way to do it using the tools showed in the same tutorial up to
    that level:


    puts "Give me the two years"
    year1 = gets.chomp.to_i
    year2 = gets.chomp.to_i
    puts "This is the list of years:"

    if year1 > year2
    puts "The second year has to be bigger than the first"
    else
    while (year1 <= year2)
    if
    (((year1 % 4 == 0) and (year1 %100 !=0)) or (year1 % 400 == 0))
    puts year1.to_s

    end
    (year1 = year1.to_i + 1)
    end
    puts "Finished"
    end
    --
    Posted via http://www.ruby-forum.com/.
    Hh Rg, Jun 23, 2010
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Hai Nguyen

    Date Validation Expression and Leap Year

    Hai Nguyen, Feb 26, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    3,319
    Hans Kesting
    Feb 27, 2004
  2. Wen
    Replies:
    4
    Views:
    466
    Simon Saunders
    Dec 12, 2003
  3. Protoman
    Replies:
    14
    Views:
    550
  4. Replies:
    8
    Views:
    508
    Howard
    Mar 30, 2007
  5. Sean
    Replies:
    6
    Views:
    117
    Evertjan.
    Apr 3, 2005
Loading...

Share This Page