diff --git a/queues/lib/priority_queue.rb b/queues/lib/priority_queue.rb new file mode 100644 index 0000000..309e107 --- /dev/null +++ b/queues/lib/priority_queue.rb @@ -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 diff --git a/queues/lib/queue.rb b/queues/lib/queue.rb index 867e804..8323292 100644 --- a/queues/lib/queue.rb +++ b/queues/lib/queue.rb @@ -1,3 +1,90 @@ class Queue + attr_reader :count -end \ No newline at end of file + 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 diff --git a/queues/test/priority_queue_test.rb b/queues/test/priority_queue_test.rb new file mode 100644 index 0000000..b2b430a --- /dev/null +++ b/queues/test/priority_queue_test.rb @@ -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 diff --git a/queues/test/queue_test.rb b/queues/test/queue_test.rb index c0b6e07..4c91b09 100644 --- a/queues/test/queue_test.rb +++ b/queues/test/queue_test.rb @@ -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 @@ -21,4 +21,46 @@ def test_it_dequeues assert_equal("C", queue.dequeue) end -end \ No newline at end of file + 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