Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DSA Dojo queue exercises #1

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions queues/lib/priority_queue.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
require "./lib/queue.rb"

class PriorityQueue
def initialize(lanes = 5)
@lanes = {}
(1..lanes).each { |i| @lanes[i] = Queue.new }
end

def enqueue(lane, plane)
@lanes[lane].enqueue(plane)
end

def next
@lanes.find { |lane, queue| !queue.empty }[1].dequeue
end

def peek
@lanes.find { |lane, queue| !queue.empty }[1].peek
end

def status
@lanes.map { |lane, queue| [lane, queue.count] }.to_h
end

def total_count
@lanes.values.map(&:count).sum
end

def queue_wait(plane)
line_count = 0

for lane, queue in @lanes
position = queue.find_position(plane)

if !position.nil?
line_count += position
break
else
line_count += queue.count
end
end

line_count
end
end

class Plane
attr_reader :name, :expected_departure, :expected_landing

def initialize(name:, expected_departure:, expected_landing:)
@name = name
@expected_departure = expected_departure
@expected_landing = expected_landing
end

def to_s
@name
end
end
89 changes: 88 additions & 1 deletion queues/lib/queue.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,90 @@
class Queue
attr_reader :count

end
def initialize
@head = Node.new(:head)
@tail = Node.new(:tail, @head)
@count = 0
end

def add(node)
@count += 1
node.right = @tail
left = @tail.left
left.right = node
@tail.left = node
end

def enqueue(x)
node = Node.new(x)
add(node)
end

def dequeue
@count -= 1
popped = @head.right
@head.right = popped.right
popped.val
end

def peek
@head.right.val
end

def last
@tail.left.val
end

def empty
@count == 0
end

def find(node)
current = @head.right
while current != nil && current.val != node
current = current.right
end
current
end

def find_position(node)
current = @head.right
count = 0
while current != nil && current.val != node
current = current.right
count += 1
end
return nil if current.nil?
count
end

def to_s
current = @head.right
str = ""
while current != nil && current != @tail
str += "#{current.val.to_s} "
current = current.right
end
str
end

def queue_wait(node)
current = @head.right
count = 0
while current != nil && current.val != node
current = current.right
count += 1
end
count
end
end

class Node
attr_accessor :val, :left, :right

def initialize(val, left = nil, right = nil)
@val = val
@left = left
@right = right
end
end
100 changes: 100 additions & 0 deletions queues/test/priority_queue_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
require "minitest"
require "minitest/autorun"
require "./lib/priority_queue.rb"

class PriorityQueueTest < Minitest::Test
def test_pq_enqueue_and_next
pq = PriorityQueue.new(3)
plane = Plane.new(name: "UA1", expected_departure: 510, expected_landing: 615)
plane2 = Plane.new(name: "UA2", expected_departure: 510, expected_landing: 615)
plane3 = Plane.new(name: "UA3", expected_departure: 510, expected_landing: 615)
pq.enqueue(2, plane2)
pq.enqueue(2, plane3)
pq.enqueue(1, plane)
next_plane = pq.next
assert_equal plane, next_plane
next_plane = pq.next
assert_equal plane2, next_plane
end

def test_pq_enqueue_and_next
pq = PriorityQueue.new(3)
plane = Plane.new(name: "UA1", expected_departure: 510, expected_landing: 615)
plane2 = Plane.new(name: "UA2", expected_departure: 510, expected_landing: 615)
plane3 = Plane.new(name: "UA3", expected_departure: 510, expected_landing: 615)
pq.enqueue(2, plane2)
pq.enqueue(2, plane3)
pq.enqueue(1, plane)
next_plane = pq.peek
assert_equal plane, next_plane
next_plane = pq.peek
assert_equal plane, next_plane
end

def test_pq_status
pq = PriorityQueue.new(3)
plane = Plane.new(name: "UA1", expected_departure: 510, expected_landing: 615)
plane2 = Plane.new(name: "UA2", expected_departure: 510, expected_landing: 615)
plane3 = Plane.new(name: "UA3", expected_departure: 510, expected_landing: 615)
pq.enqueue(2, plane2)
pq.enqueue(2, plane3)
pq.enqueue(1, plane)
status = pq.status
expected = {
1 => 1,
2 => 2,
3 => 0,
}
assert_equal expected, status
end

def test_pq_total_count
pq = PriorityQueue.new(3)
plane = Plane.new(name: "UA1", expected_departure: 510, expected_landing: 615)
plane2 = Plane.new(name: "UA2", expected_departure: 510, expected_landing: 615)
plane3 = Plane.new(name: "UA3", expected_departure: 510, expected_landing: 615)
pq.enqueue(2, plane2)
pq.enqueue(2, plane3)
pq.enqueue(1, plane)
assert_equal 3, pq.total_count
end

def test_pq_queue_wait
pq = PriorityQueue.new(3)
plane = Plane.new(name: "UA1", expected_departure: 510, expected_landing: 615)
plane2 = Plane.new(name: "UA2", expected_departure: 510, expected_landing: 615)
plane3 = Plane.new(name: "UA3", expected_departure: 510, expected_landing: 615)
pq.enqueue(2, plane2)
pq.enqueue(2, plane3)
pq.enqueue(1, plane)
actual = pq.queue_wait(plane3)
assert_equal 2, actual
end

def test_pq_queue_wait_complex
pq = PriorityQueue.new(3)
planes = [*1..10].map { |n| Plane.new(name: "UA#{n}", expected_departure: 510, expected_landing: 615) }
planes.each_with_index do |plane, i|
lane = (i % 3) + 1
pq.enqueue(lane, plane)
end

actual = pq.queue_wait(planes[7])
puts
digest = planes.each_with_index.map { |plane, i| { name: plane.name, wait: pq.queue_wait(plane), lane: (i % 3) + 1 } }
expected = [
{ name: "UA1", wait: 0, lane: 1 },
{ name: "UA2", wait: 4, lane: 2 },
{ name: "UA3", wait: 7, lane: 3 },
{ name: "UA4", wait: 1, lane: 1 },
{ name: "UA5", wait: 5, lane: 2 },
{ name: "UA6", wait: 8, lane: 3 },
{ name: "UA7", wait: 2, lane: 1 },
{ name: "UA8", wait: 6, lane: 2 },
{ name: "UA9", wait: 9, lane: 3 },
{ name: "UA10", wait: 3, lane: 1 },
]

assert_equal expected, digest
end
end
50 changes: 46 additions & 4 deletions queues/test/queue_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require 'minitest'
require 'minitest/autorun'
require './lib/queue.rb'
require "minitest"
require "minitest/autorun"
require "./lib/queue.rb"

class StackTest < Minitest::Test
def test_it_enqueues
Expand All @@ -21,4 +21,46 @@ def test_it_dequeues
assert_equal("C", queue.dequeue)
end

end
def test_it_peeks
queue = Queue.new
queue.enqueue("A")
queue.enqueue("B")
queue.enqueue("C")
assert_equal("A", queue.peek)
queue.dequeue
assert_equal("B", queue.peek)
end

def test_it_gets_last
queue = Queue.new
queue.enqueue("A")
queue.enqueue("B")
queue.enqueue("C")
assert_equal("C", queue.last)
queue.dequeue
assert_equal("C", queue.last)
end

def test_it_gets_empty
queue = Queue.new
assert_equal(true, queue.empty)
queue.enqueue("A")
assert_equal(false, queue.empty)
queue.dequeue
assert_equal(true, queue.empty)
end

def test_find_position
queue = Queue.new
"abcde".chars.each { |c| queue.enqueue(c) }
position = queue.find_position("a")
assert_equal(0, position)
end

def test_find_position_nil
queue = Queue.new
"abcde".chars.each { |c| queue.enqueue(c) }
position = queue.find_position("f")
assert_equal(nil, position)
end
end