How to get a random IP from an IP range/subnet? - ruby

Let's suppose, I have the IP Range: "52.93.50.128/32"
How can I get a random IP address that in that range?
Ruby would be preferable.

I think that this snippet using this gem should work, the easy way is to calculate the IPs range, and then select a new
#!/usr/bin/env ruby
require 'ipaddr'
family = Socket::AF_INET
subnet_range = IPAddr.new("52.93.50.128/32", family).to_range
from = subnet_range.first(2).last
to = IPAddr.new(subnet_range.last.to_i - 2, family)
puts "From: #{from}"
puts "To: #{to}"
random_ip = IPAddr.new(rand(from.to_i..to.to_i), family)
puts "Random IP: #{random_ip}"

Let's suppose, I have the IP Range: "52.93.50.128/32" How can I get a random IP address that in that range?
That's easy. This is a host address, in other words, it isn't a range at all, it is just a single address. So, you just return the input again:
def random_ip_address_from_subnet(subnet) = subnet
However, we can do something a little more intelligent, by taking into account the specifics of host addresses and RFC 3021 point-to-point links.
I am going to make an assumption here that you want only host addresses, and not network or broadcast addresses.
require 'ipaddr'
def random_ip_from_subnet(subnet)
ipaddr = IPAddr.new(subnet)
range = host_address_range(ipaddr)
range.to_a.sample
end
def host_address_range(subnet)
range = subnet.to_range
return range if rfc3021?(subnet) || host?(subnet)
Range.new(range.begin.succ, IPAddr.new(range.end.to_i - 1, subnet.family))
end
def host?(subnet) = subnet.ipv4? && subnet.prefix == 32 || subnet.ipv6? && subnet.prefix == 128
def rfc3021?(subnet) = subnet.ipv4? && subnet.prefix == 31
require 'minitest/autorun'
class TestRandomIp < Minitest::Test
def setup
#subnet_address1 = '52.93.50.129/30'
#subnet_address2 = '52.93.50.130/30'
#subnet_address_network = '52.93.50.128/30'
#subnet_address_broadcast = '52.93.50.131/30'
#subnet_address1_ip = IPAddr.new(#subnet_address1).succ
#subnet_address2_ip = #subnet_address1_ip.succ
#subnet_address_network_ip = IPAddr.new(#subnet_address_network)
#subnet_address_broadcast_ip = #subnet_address2_ip.succ
#host_address = '52.93.50.128/32'
#host_address_ip = IPAddr.new(#host_address)
#rfc3021_address1 = '52.93.50.128/31'
#rfc3021_address2 = '52.93.50.129/31'
#rfc3021_address1_ip = IPAddr.new(#rfc3021_address1)
#rfc3021_address2_ip = IPAddr.new(#rfc3021_address2).succ
end
def test_that_host_address_range_works_with_normal_subnet_addresses
range1 = host_address_range(#subnet_address1_ip)
assert_equal #subnet_address1_ip, range1.begin
assert_equal #subnet_address2_ip, range1.end
assert_equal #subnet_address1_ip..#subnet_address2_ip, range1
assert_equal 2, range1.count
range2 = host_address_range(#subnet_address2_ip)
assert_equal #subnet_address1_ip, range2.begin
assert_equal #subnet_address2_ip, range2.end
assert_equal #subnet_address1_ip..#subnet_address2_ip, range2
assert_equal 2, range2.count
range3 = host_address_range(#subnet_address_network_ip)
assert_equal #subnet_address1_ip, range3.begin
assert_equal #subnet_address2_ip, range3.end
assert_equal #subnet_address1_ip..#subnet_address2_ip, range3
assert_equal 2, range3.count
range4 = host_address_range(#subnet_address_broadcast_ip)
assert_equal #subnet_address1_ip, range4.begin
assert_equal #subnet_address2_ip, range4.end
assert_equal #subnet_address1_ip..#subnet_address2_ip, range4
assert_equal 2, range4.count
assert_equal range1, range2
assert_equal range1, range3
assert_equal range1, range4
assert_equal range2, range3
assert_equal range2, range4
assert_equal range3, range4
end
def test_that_host_address_range_works_with_host_addresses
range = host_address_range(#host_address_ip)
assert_equal #host_address_ip, range.begin
assert_equal #host_address_ip, range.end
assert_equal #host_address_ip..#host_address_ip, range
assert_equal 1, range.count
end
def test_that_host_address_range_works_with_rfc3021_addresses
range1 = host_address_range(#rfc3021_address1_ip)
assert_equal #rfc3021_address1_ip, range1.begin
assert_equal #rfc3021_address2_ip, range1.end
assert_equal #rfc3021_address1_ip..#rfc3021_address2_ip, range1
assert_equal 2, range1.count
range2 = host_address_range(#rfc3021_address2_ip)
assert_equal #rfc3021_address1_ip, range2.begin
assert_equal #rfc3021_address2_ip, range2.end
assert_equal #rfc3021_address1_ip..#rfc3021_address2_ip, range2
assert_equal 2, range2.count
assert_equal range1, range2
end
def test_that_random_ip_from_subnet_works_with_normal_subnet_addresses
100.times do
random_ip = random_ip_from_subnet(#subnet_address1)
assert [#subnet_address1_ip, #subnet_address2_ip].include?(random_ip)
end
100.times do
random_ip = random_ip_from_subnet(#subnet_address2)
assert [#subnet_address1_ip, #subnet_address2_ip].include?(random_ip)
end
100.times do
random_ip = random_ip_from_subnet(#subnet_address_network)
assert [#subnet_address1_ip, #subnet_address2_ip].include?(random_ip)
end
100.times do
random_ip = random_ip_from_subnet(#subnet_address_broadcast)
assert [#subnet_address1_ip, #subnet_address2_ip].include?(random_ip)
end
end
def test_that_random_ip_from_subnet_works_with_rfc3021_addresses
100.times do
random_ip = random_ip_from_subnet(#rfc3021_address1)
assert [#rfc3021_address1_ip, #rfc3021_address2_ip].include?(random_ip)
end
100.times do
random_ip = random_ip_from_subnet(#rfc3021_address2)
assert [#rfc3021_address1_ip, #rfc3021_address2_ip].include?(random_ip)
end
end
def test_that_random_ip_from_subnet_works_with_host_addresses
100.times do
random_ip = random_ip_from_subnet(#host_address)
assert_equal #host_address_ip, random_ip
end
end
end

Related

Ruby: TDD Plus Coding

gem 'minitest', '~> 5.2'
# TDD
require 'minitest/autorun'
require 'minitest/pride'
require_relative 'kid'
class KidTest < Minitest::Test
def test_kid_has_not_eaten_sugar
kid = Kid.new
assert_equal 0, kid.grams_of_sugar_eaten
end
def test_kid_gets_5_grams_from_eating_candy
kid = Kid.new
kid.eat_candy
assert_equal 5, kid.grams_of_sugar_eaten
5.times { kid.eat_candy }
assert_equal 30, kid.grams_of_sugar_eaten
end
def test_kid_is_not_hyperactive
kid = Kid.new
refute kid.hyperactive?
end
def test_kid_is_hyperactive_after_60_grams_of_sugar
kid = Kid.new
11.times { kid.eat_candy }
refute kid.hyperactive?, "Not hyperactive yet..."
kid.eat_candy
assert kid.hyperactive?, "OK, now the kid is hyperactive."
end
end
# CODE
class Kid
attr_reader :grams_of_sugar_eaten
def initialize
#grams_of_sugar_eaten = 0
end
def eat_candy(grams = 5)
#grams_of_sugar_eaten += grams
end
def hyperactive?
false
end
end
Can anyone help direct me in the thinking that I should have as far as how to go about getting the 2nd test to pass and so on?
I'm not sure what to do make the test pass after the kid eats 5 grams of sugar and then after 5.times to have it pass after he eats 30 grams of sugar.
Appreciate any help
You've added eat_candy as an attr_reader, not a method. The initialize function here sets eat_candy to itself.
A possible fix:
class Kid
attr_reader :grams_of_sugar_eaten
def initialize
#grams_of_sugar_eaten = 0
end
def eat_candy(grams = 5)
#grams_of_sugar_eaten += grams
end
end

Deck of cards that deals a number of cards to a number of players

I built a deck of cards:
class Card
attr_accessor :rank, :suit
def initialize(rank, suit)
#rank = rank
#suit = suit
end
def output_card
puts "#{self.rank} of #{self.suit}"
end
end
class Deck
def initialize
#cards = []
#ranks = ["Ace", 2, 3, 4, 5, 6, 7, 8, 9, 10, "Jack", "Queen", "King"]
#suits = [:hearts, :spades, :diamonds, :clubs]
#suits.each do |suit|
#ranks.each do |rank|
#cards << Card.new(rank, suit)
end
end
end
def shuffle
#cards.shuffle!
end
def deal
#cards.shift
end
def output_deck
#cards.each do |card|
card.output_card
end
end
end
deck = Deck.new
deck.shuffle
deck.deal
deck.output_deck
puts "Show top card:"
deck.deal.output_card
I am struggling to add Dealer class to deal a specified number of cards to a specified number of players.
If anyone would explain that, I would greatly appreciate it.
class Player
attr_accessor :name, :cards
def initialize(name)
#name = name
#cards = []
end
end
class HoldEmPoker
def cards_per_player
2
end
end
class Dealer
def initialize(deck, game)
#deck = deck
#game = game
end
def deal_to(player)
#game.cards_per_player.times do
player.cards << #deck.deal
end
end
end
p1 = Player.new("Negreanu")
p2 = Player.new("Ivey")
p3 = Player.new("Hellmuth")
players = [p1, p2, p3]
deck = Deck.new
deck.shuffle
game = HoldEmPoker.new
dealer = Dealer.new(deck, game)
players.each { |p| dealer.deal_to(p) }
p1.cards #=> an array with two Card objects
If you want, you can add a deal method to Dealer class
def deal(players)
players.each do |player|
#game.cards_per_player.times do
player.cards << #deck.deal
end
end
end
players = [...]
dealer.deal(players)

minitest say method missing but method is present what am I missing?

Why am I getting this undefined method error when the method is defined?
(I'm now going to wast some text so the dumb "your post is mostly code" warning goes away. Since a real developer spends most of their time reading code and this is a simple problem I don't need any more words)
Here is my error message:
$ ruby roman_numerals_test.rb
Run options: --seed 35835
# Running:
Run options: --seed 35835
# Running:
SSSSSSSSSSEE
Error:
RomanNumeralsTest#test_1:
NoMethodError: undefined method `to_roman' for 1:Integer
roman_numerals_test.rb:8:in `test_1'
bin/rails test roman_numerals_test.rb:7
Here is my test file:
gem 'minitest', '>= 5.0.0'
require 'minitest/autorun'
require_relative 'roman_numerals'
# Common test data version: 1.0.0 070e8d5
class RomanNumeralsTest < Minitest::Test
def test_1
assert_equal 'I', 1.to_roman
end
def test_2
assert_equal 'II', 2.to_roman
end
def test_3
skip
assert_equal 'III', 3.to_roman
end
def test_4
skip
assert_equal 'IV', 4.to_roman
end
def test_5
skip
assert_equal 'V', 5.to_roman
end
def test_6
skip
assert_equal 'VI', 6.to_roman
end
def test_9
skip
assert_equal 'IX', 9.to_roman
end
def test_27
skip
assert_equal 'XXVII', 27.to_roman
end
def test_48
skip
assert_equal 'XLVIII', 48.to_roman
end
def test_59
skip
assert_equal 'LIX', 59.to_roman
end
def test_93
skip
assert_equal 'XCIII', 93.to_roman
end
def test_141
skip
assert_equal 'CXLI', 141.to_roman
end
def test_163
skip
assert_equal 'CLXIII', 163.to_roman
end
def test_402
skip
assert_equal 'CDII', 402.to_roman
end
def test_575
skip
assert_equal 'DLXXV', 575.to_roman
end
def test_911
skip
assert_equal 'CMXI', 911.to_roman
end
def test_1024
skip
assert_equal 'MXXIV', 1024.to_roman
end
def test_3000
skip
assert_equal 'MMM', 3000.to_roman
end
def test_bookkeeping
assert_equal 2, BookKeeping::VERSION
end
end
And here is my code:
module BookKeeping
VERSION = 2
end
class Numeral
def initialize(number)
#number = number
end
def to_roman
roman_hash = {
1000 => 'M',
900 => 'CM',
500 => 'D',
400 => 'CD',
100 => 'C',
90 => 'XC',
50 => 'L',
40 => 'XL',
10 => 'X',
9 => 'IX',
5 => 'V',
4 => 'IV',
1 => 'I'
}
my_string = ""
roman_hash.each do |key, value|
(#number / key).times {my_string << value; #number = #number - key}
end
my_string
end
end
You're defining to_roman for Numeral objects but 1 is an Integer. Try
class Integer
or
class Numeric
(superclass of Integer)

Implement and test Card and Deck classes in Ruby

I am having a little trouble getting my code to run and have been at it for at least 4 hours...I can't seem to figure it out. BTW I am a newb at programming.
This is the UML diagram for the card/deck
http://imgur.com/lBJw2z0
class Card
#Cards rank from lowest to highest
VALUE = %w(2 3 4 5 6 7 8 9 10 J Q K A)
SUITS = %w(C D H S)
#(Club Diamond Heart Spade)
def initialize(the_rank, the_suit)
[#rank = the_rank]
[#suit = the_suit]
[#symbols = [nil, nil, '2', '3', '4', '5', '6', '7',
'8', '9', '10', 'J', 'Q', 'K', 'A']
end
def rank
[return #symbols[#rank]]
end
def suit
return #suit
end
def to_s
"#{rank()}#{suit()}"
end
end
#double loop for Deck#initialize
#cards = [ ]
for rank in 2..14
for suit in ['C', 'D', 'H', 'S']
# create a new card with the specified rank
# and suit and append it to the array.
end
end
suits.each do |suit|
(ranks.size).times do |i|
#cards.push(Card.new(ranks[i], suit,(i+1)))
end
end
#Remove a card from the top
def deal
[#cards.pop()](1)
end
#Add card to the bottom of the deck
def add_to_bottom(the_card)
#cards.insert(0, the_card)
end
#Add card to the top of the deck
def add_to_top(the_card)
#cards << the_card
end
#Shuffle the Card objects in the deck
def shuffle!
#cards.shuffle!
end
def count()
#cards.count()
end
def empty?
#cards.length == 0
end
def to_s
string = ""
#cards.each do |card|
string += card.to_s + " "
end
end
def cards
#cards
end
end
I haven't tested this very thoroughly, but it basically implements the UML diagram you linked to:
class Deck
def initialize
#ranks = %w(2 3 4 5 6 7 8 9 10 J Q K A)
#suits = %w(Clubs Diamonds Hearts Spades)
#cards = []
#ranks.each do |rank|
#suits.each do |suit|
#cards << Card.new(rank, suit)
end
end
end
def deal
#cards.shift
end
def add_to_bottom(card)
#cards.unshift(card)
end
def add_to_top(card)
#cards << card
end
def count
#cards.count
end
def empty?
#cards.empty?
end
def shuffle!
#cards.shuffle
end
def to_s
result = ''
#cards.each do |card|
result = result + card.to_s + "\n"
end
return result
end
end
class Card
attr_reader :rank, :suit, :color
def initialize(rank, suit)
#rank = rank
#suit = suit
if #rank == 'Clubs' || #rank == 'Spades'
#color = 'black'
else
#color = 'red'
end
end
def to_s
"Card: #{#color} #{#rank} of #{#suit}"
end
end
# Run it, and try some stuff...
my_deck = Deck.new
puts my_deck.to_s
my_deck.deal
my_deck.count
my_deck.shuffle!
puts my_deck.to_s
my_deck.deal
my_deck.count
Now I am trying to figure how the testing method. I have the first working
d = Deck.new
d.cards.each do |card|
puts "#{card.rank} #{card.suit}"
end
And the second method that needs to test:
tests both the Card and Deck classes using the unit test framework with assert_equal methods. Write unit tests for all methods in the Card class, but you only have to test these methods in the Deck class: new, deal, add_to_bottom, add_to_top, count, empty?

Creating custom array class in Ruby and struggling with a basic piece of functionality

I'm creating a class that creates arrays. (Yes, I realize that's already available in ruby. This is more of an exercise.) The class, SpecialArray, creates an array based on input that's either given by the user when creating a new array or added to the array later. I'm having trouble connecting these two pieces of functionality. Creating an array works fine, but adding to it does not. I had thought that the output atrr_reader would hold the exiting array in memory, but now I'm not sure. Any idea how I can make this work?
class SpecialArray
attr_reader :input, :output
def initialize(*input)
#input = input.flatten
#output = []
generate_array
end
def generate_array
input.each do |e|
add(e)
end
output
end
#update start
def numerical(element)
element.class == Fixnum
end
def unique(element)
output.include? element ? false : true
end
def valid_e(element)
unique(element) && numerical(element)
end
def numerical(elment)
element.class == Fixnum
end
def unique(element)
output.include? element ? false : true
end
def valid_e(element)
unique(element) && numerical(element)
end
#update end
def add(element)
unless valid_e(element) == false
output.push(element)
end
output
end
end
Seems to work fine to me, both #input and #output contain the array I passed in:
irb(main):032:0> a = SpecialArray.new(1,2,3,4,5,6,7);
irb(main):034:0> puts a.inspect
#<SpecialArray:0x296e7e8 #input=[1, 2, 3, 4, 5, 6, 7],
#output=[1, 2, 3, 4, 5, 6, 7]>
=> nil
EDIT Full Code
irb(main):001:0> class SpecialArray
irb(main):002:1> attr_reader :input, :output
irb(main):003:1>
irb(main):004:1* def initialize(*input)
irb(main):005:2> #input = input.flatten
irb(main):006:2> #output = []
irb(main):007:2> generate_array
irb(main):008:2> end
irb(main):009:1>
irb(main):010:1* def generate_array
irb(main):011:2> input.each do |e|
irb(main):012:3* add(e)
irb(main):013:3> end
irb(main):014:2> output
irb(main):015:2> end
irb(main):016:1>
irb(main):017:1* #...
irb(main):018:1*
irb(main):019:1* def add(element)
irb(main):020:2> unless valid_e(element) == false
irb(main):021:3> output.push(element)
irb(main):022:3> end
irb(main):023:2> output
irb(main):024:2> end
irb(main):025:1>
irb(main):026:1* def valid_e(e)
irb(main):027:2> return true;
irb(main):028:2* end
irb(main):029:1>
irb(main):030:1* #...
irb(main):031:1* end
=> nil
irb(main):032:0> a = SpecialArray.new(1,2,3,4,5,6,7);
irb(main):034:0> puts a.inspect
#<SpecialArray:0x296e7e8 #input=[1, 2, 3, 4, 5, 6, 7],
#output=[1, 2, 3, 4, 5, 6, 7]>
=> nil

Resources