Trouble with a while loop

Discussion in 'Ruby' started by Bashka Dooble, Nov 30, 2007.

  1. Hi,

    Please forgive if this forum is not the right one for this post.

    I'm writing a small ruby program that implements sale of a plot of land
    to 5 investors through English Auction. In an English auction, the
    auctioneer begins the auction with the reserve price (lowest acceptable
    price) and then takes larger and larger bids from the customers until no
    one will increase the bid. The item is then sold to the highest bidder.

    The logic that i'm using to decide which investor to bid first is this:
    1. Each investor has a maximum willing price that they can't exceed.
    2. First find out the difference/margin btw an investor's willing price
    and the reserve price
    3. The investor that has the lowest margin bids first
    4. An investor's first bid = reserve price + half of margin
    5. Subsequent bids = first bid + 25% of margin i.e. half of the other
    half of margin

    The code as it is now is attached.

    Thanks,

    Bashka

    Attachments:
    http://www.ruby-forum.com/attachment/1072/engBid42.rb

    --
    Posted via http://www.ruby-forum.com/.
    Bashka Dooble, Nov 30, 2007
    #1
    1. Advertising

  2. Hi Bashka,

    I've had a it of a shot at your code, mainly looking at reducing the
    repetition and catching a few of the cases that might cause an endless
    loop (like if no-one bid higher than the valuation.

    It looks from your code like you newish to programming, so there's a
    fair chance I've used some constructs not familiar to you. If so, let
    us know and someone will help explain. This is only a quick attempt
    (I'm supposed to be unpacking boxes - we've just moved house) and a
    bit messy.

    Here tis:

    class Bidder
    attr_reader :still_bidding, :num

    def initialize num, reserve_price, max_bid
    @num= num
    @max_bid= max_bid
    @margin= @max_bid- reserve_price
    @bid= reserve_price+ @margin/2
    @still_bidding= @max_bid> reserve_price
    end

    def current_bid
    @bid
    end

    def raise_bid
    @bid+= @margin/4
    @still_bidding= @bid<= @max_bid
    end
    end

    @bidders= []

    def get_num msg
    print "#{msg} >"
    gets.to_i
    end

    #we're only interested in bidders who haven't yet reached their max
    def bidders_left
    @bidders.select {|bidder| bidder.still_bidding}
    end

    valuation= get_num "Enter the valuation"
    reserve_price= get_num "Enter the reserve price"

    #set up the bidders
    (1..(get_num "How many bidders?")).each do |index|
    max_bid= get_num "How much is invester #{index} willing to spend?"
    @bidders << Bidder.new(index, reserve_price, max_bid)
    end

    #no-one's won yet, and we haven't started
    winner= nil
    round= 0

    while bidders_left.any? && winner.nil?
    print "\nRound #{round+=1}: "

    #get the current lowest bidder
    current_bidder= bidders_left.sort{|a,b| a.current_bid <=>
    b.current_bid}.first

    bid= current_bidder.current_bid
    puts "Investor #{current_bidder.num} is bidding $#{bid}"

    #either they won, or they raise their bid
    if bid> valuation
    winner= current_bidder
    else
    current_bidder.raise_bid
    end
    end

    if winner.nil?
    puts "No one bid high enough. Property passed in"
    else
    puts "** This property has been sold to Invester
    #{current_bidder.num} **"
    end


    On 30/11/2007, at 8:00 PM, Bashka Dooble wrote:

    > Hi,
    >
    > Please forgive if this forum is not the right one for this post.
    >
    > I'm writing a small ruby program that implements sale of a plot of
    > land
    > to 5 investors through English Auction. In an English auction, the
    > auctioneer begins the auction with the reserve price (lowest
    > acceptable
    > price) and then takes larger and larger bids from the customers
    > until no
    > one will increase the bid. The item is then sold to the highest
    > bidder.
    >
    > The logic that i'm using to decide which investor to bid first is
    > this:
    > 1. Each investor has a maximum willing price that they can't exceed.
    > 2. First find out the difference/margin btw an investor's willing
    > price
    > and the reserve price
    > 3. The investor that has the lowest margin bids first
    > 4. An investor's first bid = reserve price + half of margin
    > 5. Subsequent bids = first bid + 25% of margin i.e. half of the other
    > half of margin
    >
    > The code as it is now is attached.
    >
    > Thanks,
    >
    > Bashka
    >
    > Attachments:
    > http://www.ruby-forum.com/attachment/1072/engBid42.rb
    >
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    Sharon Phillips, Nov 30, 2007
    #2
    1. Advertising

  3. Hi Sharon,

    Many many thanks for your kind response. As you guessed I'm new to
    programming. The code works fine. Only it doesn't display messages
    asking for user input, for instance "Enter the valuation" message
    doesn't appear.

    Much appreciated though and God bless.

    Best regards,

    Bishar

    --
    Posted via http://www.ruby-forum.com/.
    Bashka Dooble, Nov 30, 2007
    #3
  4. > Hi Sharon,
    Everyone says that...
    I'm actually Dave, but I use my wife's email :)

    > Many many thanks for your kind response. As you guessed I'm new to
    > programming. The code works fine. Only it doesn't display messages
    > asking for user input, for instance "Enter the valuation" message
    > doesn't appear.

    What sort of environment are you running this on?
    Perhaps you could alter get_num to include STDOUT.flush (like your
    original)

    def get_num msg
    print "#{msg} >"
    STDOUT.flush
    gets.to_i
    end


    Probably the most important thing I'd like to get across is that
    whenever you see yourself writing something like
    a_margin = max_price_A - reservePrice
    b_margin = max_price_B - reservePrice
    c_margin = max_price_C - reservePrice
    d_margin = max_price_D - reservePrice
    e_margin = max_price_E - reservePrice

    you're repeating yourself unnecessarily and making it difficult to
    change the programme (what if we had an extra investor? what if we had
    100?)
    Ruby (unlike a number of other languages) makes it very simple to
    manage lists of things.

    Here's your original code again, but all I've done is put all the
    a_margin (etc) bits into a list and change the bidding section to use
    this list

    Cheers,
    Dave

    # set up list (array) to hold our investor information
    investors= []

    # Change the number of bidders by changing this value
    BIDDER_COUNT=5

    #Get the valuation price i.e the Auctioneer's expected price of the
    property
    puts"Enter the valuation: "
    STDOUT.flush
    valuation = gets.to_i

    #Get the Reserve price i.e. the minimum acceptable price of the property
    puts "Enter the reserve price: "
    STDOUT.flush
    reservePrice = gets.to_i

    # get the max_price for each investor
    for index in (1..BIDDER_COUNT)
    # we'll use a hash to keep all the information we need about this
    investor
    # much tidier than having sperate lists for bids, margins and
    max_prices
    this_investor= {:index => index}

    #Each agent knows the maximun amount it can afford to pay for the
    property
    puts "How much is invester #{index} willing to spend? "
    STDOUT.flush
    this_investor[:max_price]= gets.to_i

    # add the new investor to our list
    investors << this_investor
    end

    investors.each do |investor|
    #Calculate invester bid magins
    #i.e. difference btw an agent's max willing price and the reserve
    price
    investor[:margin] = investor[:max_price] - reservePrice

    #Initialize bids for the investers here. First bid is reserve price
    plus half of the margin.
    #The other half will be incrementally bidded at 50% per round of
    bidding
    investor[:bid] = reservePrice + investor[:margin]/2
    end

    =begin
    Assumptions
    1. Probability of two or more investers having the same max price is
    negligible
    2. Investers do not know each other's willing prices
    3. A margin can't be zero...to be explained later
    =end

    #Continue bidding as long as the highest bid is less or equal to
    valuation price.
    #Trivially, the property will be sold to the agent that reaches or
    exceeds the valuation price

    # keep going untill we have a winner.
    # NOTE ** this will continue forever if none of the bidders has a
    max_price
    # >= the valuation
    # You'll need to add a check for this as well
    # Hint: you'll reach a round where those_still_bidding will be empty
    # (everyone has dropped out)

    #initialize out winner as no one
    winner= nil

    while winner.nil? do
    # check who should bid first
    # we need to find the lowest bid that's not greater than that
    investors'
    # max_price

    # To do this, let's take out list of investors, and narrow it down
    to only
    # those still bidding (bid <= max_price)


    those_still_bidding= investors.select do |investor|
    # if the following evaluates as true, this investor will join our
    new list
    investor[:bid] <= investor[:max_price]
    end

    # Now, from those let's find the lowest bidder.
    # One way to do this is to sort the list by bid, then pick the
    first one
    # Step 1: sort them
    those_still_bidding.sort! do |investor_a, investor_b|
    investor_a[:bid] <=> investor_b[:bid]
    end
    # Step 2: get the first
    lowest_bidder= those_still_bidding.first

    puts "Investor #{lowest_bidder[:index]} is bidding
    #{lowest_bidder[:bid]}"

    # Two possibilities now:
    # 1: This bid wins, and the action ends
    # 2: This bid doesn't win, this investor raises their bid and we
    continue
    if lowest_bidder[:bid]>= valuation then
    # Only need to set winner here.
    # This will cause the while loop to stop (winner is no longer nil)
    # We'll display the winning details at the end
    winner= lowest_bidder
    else
    lowest_bidder[:bid]+= lowest_bidder[:margin] * 0.25
    end

    end # whle

    # The programme will only get to here once a winner has been declared

    puts "\nThis property has been sold to Invester #{winner[:index]} for
    #{winner[:bid]}"
    Sharon Phillips, Nov 30, 2007
    #4
  5. Hi Dave,

    I'm sure you don't mind that :)

    Actually there's no problem with the code, it was me behaving stupid
    newish. Again I appreciate your help. I guess it's through such forums
    as ruby-forum that morons like me get to learn and like programming.

    Best regards,

    Bishar


    --
    Posted via http://www.ruby-forum.com/.
    Bashka Dooble, Dec 4, 2007
    #5
    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. Steven

    while loop in a while loop

    Steven, Mar 24, 2005, in forum: Java
    Replies:
    5
    Views:
    2,228
    Tim Slattery
    Mar 30, 2005
  2. Daniel Pitts
    Replies:
    14
    Views:
    1,230
    Patricia Shanahan
    Dec 23, 2006
  3. Uday Bidkar
    Replies:
    4
    Views:
    487
    =?ISO-8859-15?Q?Juli=E1n?= Albo
    Dec 12, 2006
  4. Roedy Green
    Replies:
    3
    Views:
    427
    Mike Schilling
    Sep 13, 2008
  5. Isaac Won
    Replies:
    9
    Views:
    369
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page