From 8510fe3251dac83f32b0851e493e284be00b4b0c Mon Sep 17 00:00:00 2001 From: Mike Schutte Date: Mon, 6 Nov 2023 21:40:16 -0500 Subject: [PATCH 1/4] queue passing --- queues/lib/queue.rb | 46 ++++++++++++++++++++++++++++++++++++++- queues/test/queue_test.rb | 36 ++++++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/queues/lib/queue.rb b/queues/lib/queue.rb index 867e804..0f6e665 100644 --- a/queues/lib/queue.rb +++ b/queues/lib/queue.rb @@ -1,3 +1,47 @@ 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 enqueue(x) + @count += 1 + node = Node.new(x) + node.right = @tail + left = @tail.left + left.right = node + @tail.left = 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 +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/queue_test.rb b/queues/test/queue_test.rb index c0b6e07..6bf1b78 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,32 @@ 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 +end From be513d7d253a02239c0a75e9acbb56e09c64d2a7 Mon Sep 17 00:00:00 2001 From: Mike Schutte Date: Mon, 6 Nov 2023 22:14:15 -0500 Subject: [PATCH 2/4] priority queue rd 1 --- queues/lib/priority_queue.rb | 34 ++++++++++++++++++++ queues/lib/queue.rb | 8 +++-- queues/test/priority_queue_test.rb | 50 ++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 queues/lib/priority_queue.rb create mode 100644 queues/test/priority_queue_test.rb diff --git a/queues/lib/priority_queue.rb b/queues/lib/priority_queue.rb new file mode 100644 index 0000000..027d3e2 --- /dev/null +++ b/queues/lib/priority_queue.rb @@ -0,0 +1,34 @@ +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 +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 +end diff --git a/queues/lib/queue.rb b/queues/lib/queue.rb index 0f6e665..b8ff1db 100644 --- a/queues/lib/queue.rb +++ b/queues/lib/queue.rb @@ -7,15 +7,19 @@ def initialize @count = 0 end - def enqueue(x) + def add(node) @count += 1 - node = Node.new(x) 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 diff --git a/queues/test/priority_queue_test.rb b/queues/test/priority_queue_test.rb new file mode 100644 index 0000000..4ef47e0 --- /dev/null +++ b/queues/test/priority_queue_test.rb @@ -0,0 +1,50 @@ +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 +end From 15f32eca81069e2f0709fde169918acedc069f15 Mon Sep 17 00:00:00 2001 From: Mike Schutte Date: Mon, 6 Nov 2023 23:14:05 -0500 Subject: [PATCH 3/4] queue wait --- queues/lib/priority_queue.rb | 17 ++++++++++ queues/lib/queue.rb | 28 +++++++++++++++++ queues/test/priority_queue_test.rb | 50 ++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/queues/lib/priority_queue.rb b/queues/lib/priority_queue.rb index 027d3e2..54f7d55 100644 --- a/queues/lib/priority_queue.rb +++ b/queues/lib/priority_queue.rb @@ -21,6 +21,19 @@ def peek 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) + ahead = @lanes.slice_after { |lane, queue| queue.find(plane) }.first.reverse + lane, *rest = ahead.map(&:last) + within_lane_count = lane.queue_wait(plane) + priority_ahead_count = rest.map(&:count).sum + + within_lane_count + priority_ahead_count + end end class Plane @@ -31,4 +44,8 @@ def initialize(name:, expected_departure:, expected_landing:) @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 b8ff1db..d1dd900 100644 --- a/queues/lib/queue.rb +++ b/queues/lib/queue.rb @@ -38,6 +38,34 @@ def last def empty @count == 0 end + + def find(node) + current = @head + while current != nil && current.val != node + current = current.right + end + current + 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 diff --git a/queues/test/priority_queue_test.rb b/queues/test/priority_queue_test.rb index 4ef47e0..b2b430a 100644 --- a/queues/test/priority_queue_test.rb +++ b/queues/test/priority_queue_test.rb @@ -47,4 +47,54 @@ def test_pq_status } 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 From 99c1649b1148d23e140c8c635ae5542095a5f3b1 Mon Sep 17 00:00:00 2001 From: Mike Schutte Date: Tue, 7 Nov 2023 06:34:33 -0500 Subject: [PATCH 4/4] queue_wait without enumerable --- queues/lib/priority_queue.rb | 18 +++++++++++++----- queues/lib/queue.rb | 13 ++++++++++++- queues/test/queue_test.rb | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/queues/lib/priority_queue.rb b/queues/lib/priority_queue.rb index 54f7d55..309e107 100644 --- a/queues/lib/priority_queue.rb +++ b/queues/lib/priority_queue.rb @@ -27,12 +27,20 @@ def total_count end def queue_wait(plane) - ahead = @lanes.slice_after { |lane, queue| queue.find(plane) }.first.reverse - lane, *rest = ahead.map(&:last) - within_lane_count = lane.queue_wait(plane) - priority_ahead_count = rest.map(&:count).sum + line_count = 0 - within_lane_count + priority_ahead_count + 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 diff --git a/queues/lib/queue.rb b/queues/lib/queue.rb index d1dd900..8323292 100644 --- a/queues/lib/queue.rb +++ b/queues/lib/queue.rb @@ -40,13 +40,24 @@ def empty end def find(node) - current = @head + 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 = "" diff --git a/queues/test/queue_test.rb b/queues/test/queue_test.rb index 6bf1b78..4c91b09 100644 --- a/queues/test/queue_test.rb +++ b/queues/test/queue_test.rb @@ -49,4 +49,18 @@ def test_it_gets_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