Why does this choke?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • S Kemplay

    Why does this choke?

    Hi all,

    I wrote a script to choose random dates for a statistics assignment.
    I only need to choose 30 dates from one year with no leap years and it works
    fine. However I tested with different numbers of dates. It hangs from 450up.
    I only need 30 dates but it would be good to know why it hangs. (My coding
    probably has something to do with it :))


    import random

    def getmonth():
    month = random.randint( 1,12)
    return month

    def getday(month, leaps):
    thirtyones = [1,3,5,7,8,10,12]
    thirties = [4,6,9,11]
    if month in thirtyones:
    day = random.randint( 1,31)
    elif month in thirties:
    day = random.randint( 1,30)
    else:
    if leaps == 1: leap = random.randint( 1,4)
    else: leap = 1
    if leap in [2,3,4]:
    day = random.randint( 1,29)
    else:
    day = random.randint( 1,28)
    return day

    def getdates(n, leaps):
    dates = []
    i = 0
    while i < n:
    month = getmonth()
    day = getday(month, leaps)
    if (day, month) in dates:
    continue
    i += 1
    dates.append((d ay, month))
    return dates


    Thanks

    Sean Kemplay

  • Dennis Lee Bieber

    #2
    Re: Why does this choke?

    S Kemplay fed this fish to the penguins on Friday 07 November 2003
    03:29 am:
    [color=blue]
    > I wrote a script to choose random dates for a statistics assignment.
    > I only need to choose 30 dates from one year with no leap years and it[/color]

    "... with no leap years..." so why do you have that mess for leap year
    February length?
    [color=blue]
    > works fine. However I tested with different numbers of dates. It hangs
    > from 450 up. I only need 30 dates but it would be good to know why it
    > hangs. (My coding probably has something to do with it :))
    >[/color]
    You don't show the main program invocation... However... How much time
    did you let the program run? Your code is asking for UNIQUE random
    dates -- no duplicates (which doesn't seem to be something I'd expect
    in a statistical test). As a result, you have this growing list of
    dates that has to be compared each time you generate a new date. For a
    short list this may not be noticeable, but for longer lists it takes
    time!

    Oh! That's it -- you are generating 450 UNIQUE DATES, but there are a
    maximum of 366 possible (since you don't keep the year)... The loop
    will NEVER END since once the first 366 are used, it can not generate a
    valid unique date.

    You are also generating an awful lot of random numbers... Try the
    following (watch out for line wraps)

    -=-=-=-=-=-=-=-=-

    import random

    # start with MARCH to avoid the confusion of 365 vs 366 (leap)
    MONTHS = [ 'Mar', 'Apr', 'May',
    'Jun', 'Jul', 'Aug',
    'Sep', 'Oct', 'Nov',
    'Dec', 'Jan', 'Feb' ]

    # a list of the start day for each month
    LENGTH = [ 1, 32, 62,
    93, 123, 154,
    185, 215, 246,
    276, 307, 338 ]

    def RandomDate():
    # generate a random date index within a normal year
    dayindex = random.randint( 1, 365)
    # check for a leap year date (though your requirements
    # say "no leap years", and without having a year attached
    # this just confuses statistics)
    if random.randint( 1, 4) == 4:
    dayindex += 1

    monthindex = 0
    while monthindex < 11:
    # scan LENGTH to find which month
    if dayindex < LENGTH[monthindex]: break
    monthindex += 1

    monthindex -= 1 # adjust for last loop

    month = MONTHS[monthindex]
    day = dayindex - LENGTH[monthindex]

    return (month, day)


    if __name__ == "__main__":
    dates = []
    while len(dates) < 450: # if the limit is >365, do not use UNIQUE
    aDate = RandomDate()
    dates.append(aD ate) # replace this with next two for UNIQUE
    # if aDate not in dates:
    # dates.append(aD ate)


    print dates



    --[color=blue]
    > =============== =============== =============== =============== == <
    > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
    > wulfraed@dm.net | Bestiaria Support Staff <
    > =============== =============== =============== =============== == <
    > Bestiaria Home Page: http://www.beastie.dm.net/ <
    > Home Page: http://www.dm.net/~wulfraed/ <[/color]

    Comment

    • Dennis Lee Bieber

      #3
      Re: Why does this choke?

      Dennis Lee Bieber fed this fish to the penguins on Friday 07 November
      2003 08:55 am:

      Obviously I wasn't full awake when I wrote that -- a few bugs were
      left... I think this one is more suited:

      import random

      # start with MARCH to avoid the confusion of 365 vs 366 (leap)
      MONTHS = [ 'Mar', 'Apr', 'May',
      'Jun', 'Jul', 'Aug',
      'Sep', 'Oct', 'Nov',
      'Dec', 'Jan', 'Feb' ]

      # a list of the start day for each month
      LENGTH = [ 1, 32, 62,
      93, 123, 154,
      185, 215, 246,
      276, 307, 338 ]

      def RandomDate():
      # generate a random date index within a year
      if random.randint( 1, 4) == 4:
      dayindex = random.randint( 1, 366)
      else:
      dayindex = random.randint( 1, 365)

      monthindex = 0
      while monthindex < 12:
      # scan LENGTH to find which month
      if dayindex < LENGTH[monthindex]: break
      monthindex += 1

      monthindex -= 1 # adjust for last loop

      month = MONTHS[monthindex]
      day = dayindex - LENGTH[monthindex] + 1

      return (month, day)


      if __name__ == "__main__":
      dates = []
      while len(dates) < 450: # if the limit is >365, do not use UNIQUE
      aDate = RandomDate()
      dates.append(aD ate) # replace this with next two for UNIQUE
      # if aDate not in dates:
      # dates.append(aD ate)


      print dates

      --[color=blue]
      > =============== =============== =============== =============== == <
      > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
      > wulfraed@dm.net | Bestiaria Support Staff <
      > =============== =============== =============== =============== == <
      > Bestiaria Home Page: http://www.beastie.dm.net/ <
      > Home Page: http://www.dm.net/~wulfraed/ <[/color]

      Comment

      • S Kemplay

        #4
        Re: Why does this choke?

        Hi Dennis,

        Thanks for your advice,

        I really like the way you handled the dates and can see your script generates
        fewer random numbers for each date generated.

        It still has to check whether the dates in the list (for unique dates). I
        guess breaking a big list down into shorter lists would help?

        Sean Kemplay



        On Saturday 08 November 2003 18:33, Dennis Lee Bieber wrote:[color=blue]
        > Dennis Lee Bieber fed this fish to the penguins on Friday 07 November
        > 2003 08:55 am:
        >
        > Obviously I wasn't full awake when I wrote that -- a few bugs were
        > left... I think this one is more suited:
        >
        > import random
        >
        > # start with MARCH to avoid the confusion of 365 vs 366 (leap)
        > MONTHS = [ 'Mar', 'Apr', 'May',
        > 'Jun', 'Jul', 'Aug',
        > 'Sep', 'Oct', 'Nov',
        > 'Dec', 'Jan', 'Feb' ]
        >
        > # a list of the start day for each month
        > LENGTH = [ 1, 32, 62,
        > 93, 123, 154,
        > 185, 215, 246,
        > 276, 307, 338 ]
        >
        > def RandomDate():
        > # generate a random date index within a year
        > if random.randint( 1, 4) == 4:
        > dayindex = random.randint( 1, 366)
        > else:
        > dayindex = random.randint( 1, 365)
        >
        > monthindex = 0
        > while monthindex < 12:
        > # scan LENGTH to find which month
        > if dayindex < LENGTH[monthindex]: break
        > monthindex += 1
        >
        > monthindex -= 1 # adjust for last loop
        >
        > month = MONTHS[monthindex]
        > day = dayindex - LENGTH[monthindex] + 1
        >
        > return (month, day)
        >
        >
        > if __name__ == "__main__":
        > dates = []
        > while len(dates) < 450: # if the limit is >365, do not use
        > UNIQUE aDate = RandomDate()
        > dates.append(aD ate) # replace this with next two
        > for UNIQUE # if aDate not in dates:
        > # dates.append(aD ate)
        >
        >
        > print dates[/color]


        Comment

        Working...