local :Q queue
!. empty Q
enqueue Q "HELLO"
enqueue Q 123
enqueue Q "It's a magical place"
!. empty Q
!. dequeue Q
!. dequeue Q
!. dequeue Q
!. empty Q
!. dequeue Q


def [reader, writer] := makeQueue()
require(escape empty { reader.dequeue(empty); false } catch _ { true })
writer.enqueue(1)
writer.enqueue(2)
require(reader.dequeue(throw) == 1)
writer.enqueue(3)
require(reader.dequeue(throw) == 2)
require(reader.dequeue(throw) == 3)
require(escape empty { reader.dequeue(empty); false } catch _ { true })


import system'collections;
import extensions;

public program()
{
    // Create a queue and "push" items into it
    var queue := new Queue();

    queue.push:1;
    queue.push:3;
    queue.push:5;

    // "Pop" items from the queue in FIFO order
    console.printLine(queue.pop()); // 1
    console.printLine(queue.pop()); // 3
    console.printLine(queue.pop()); // 5

    // To tell if the queue is empty, we check the count
    console.printLine("queue is ",(queue.Length == 0).iif("empty","nonempty"));

    // If we try to pop from an empty queue, an exception
    // is thrown.
    queue.pop() | on:(e){ console.writeLine:"Queue empty." }
}


defmodule Queue do
  def empty?([]), do: true
  def empty?(_), do: false

  def pop([h|t]), do: {h,t}

  def push(q,t), do: q ++ [t]

  def front([h|_]), do: h
end


1> Q = fifo:new().
{fifo,[],[]}
2> fifo:empty(Q).
true
3> Q2 = fifo:push(Q,1).
{fifo,[1],[]}
4> Q3 = fifo:push(Q2,2).
{fifo,[2,1],[]}
5> fifo:empty(Q3).
false
6> fifo:pop(Q3).
{1,{fifo,[],[2]}}
7> {Popped, Q} = fifo:pop(Q2).
{1,{fifo,[],[]}}
8> fifo:pop(fifo:new()).
** exception error: 'empty fifo'
     in function  fifo:pop/1


USING: combinators deques dlists kernel prettyprint ;
IN: rosetta-code.queue-usage

DL{ } clone {                ! make new queue
    [ [ 1 ] dip push-front ] ! push 1
    [ [ 2 ] dip push-front ] ! push 2
    [ [ 3 ] dip push-front ] ! push 3
    [ .                    ] ! DL{ 3 2 1 }
    [ pop-back drop        ] ! pop 1 (and discard)
    [ pop-back drop        ] ! pop 2 (and discard)
    [ pop-back drop        ] ! pop 3 (and discard)
    [ deque-empty? .       ] ! t
} cleave


class Main
{
  public static Void main ()
  {
    q := Queue()
    q.push (1)
    q.push ("a")
    echo ("Is empty? " + q.isEmpty)
    echo ("Element: " + q.pop)
    echo ("Element: " + q.pop)
    echo ("Is empty? " + q.isEmpty)
    try { q.pop } catch (Err e) { echo (e.msg) }
  }
}


: cqueue: ( n -- <text>)
    create                                                 \ compile time: build the data structure in memory
        dup
        dup 1- and abort" queue size must be power of 2"
        0 ,                                                \ write pointer "HEAD"
        0 ,                                                \ read  pointer "TAIL"
        0 ,                                                \ byte counter
        dup 1- ,                                           \ mask value used for wrap around
        allot ;                                            \ run time: returns the address of this data structure

\ calculate offsets into the queue data structure
: ->head ( q -- adr )      ;                               \ syntactic sugar
: ->tail ( q -- adr ) cell+   ;
: ->cnt  ( q -- adr ) 2 cells +   ;
: ->msk  ( q -- adr ) 3 cells +   ;
: ->data ( q -- adr ) 4 cells +   ;

: head++ ( q -- )                                         \ circular increment head pointer of a queue
         dup >r ->head @ 1+  [email protected] ->msk @ and r> ->head ! ;

: tail++ ( q -- )                                         \ circular increment tail pointer of a queue
        dup >r  ->tail @ 1+  [email protected] ->msk @ and r> ->tail ! ;

: qempty ( q -- flag)
        dup ->head off   dup ->tail off  dup ->cnt  off    \ reset all fields to "off" (zero)
        ->cnt @ 0=  ;                                      \ per the spec qempty returns a flag

: cnt=msk?   ( q -- flag)  dup >r  ->cnt @ r> ->msk @ = ;
: ?empty     ( q -- )     ->cnt @ 0=  abort" queue is empty" ;
: ?full      ( q -- )     cnt=msk? abort" queue is full" ;
: 1+!   ( adr -- )  1 swap +! ;                            \ increment contents of adr
: 1-!   ( adr -- ) -1 swap +! ;          \ decrement contents of adr

: [email protected]    ( queue -- char )                                 \ fetch next char in queue
       dup >r ?empty                                       \ abort if empty
       [email protected] ->cnt 1-!                                        \ decr. the counter
       [email protected] tail++
       [email protected] ->data  r> ->tail @ + [email protected] ;                       \ calc. address and fetch the byte

: qc!    ( char queue -- )
       dup >r ?full                                        \ abort if q full
       [email protected] ->cnt 1+!                                        \ incr. the counter
       [email protected] head++
       [email protected] ->data  r> ->head @ + c! ;                       \ data+head = adr, and store the char


module fifo_nodes
  type fifo_node
     integer :: datum
     ! the next part is not variable and must be present
     type(fifo_node), pointer :: next
     logical :: valid
  end type fifo_node
end module fifo_nodes

program FIFOTest
  use fifo
  implicit none

  type(fifo_head) :: thehead
  type(fifo_node), dimension(5) :: ex, xe
  integer :: i

  call new_fifo(thehead)

  do i = 1, 5
     ex(i)%datum = i
     call fifo_enqueue(thehead, ex(i))
  end do

  i = 1
  do
     call fifo_dequeue(thehead, xe(i))
     print *, xe(i)%datum
     i = i + 1
     if ( fifo_isempty(thehead) ) exit
  end do

end program FIFOTest


' FB 1.05.0 Win64

#Include "queue_rosetta.bi"  '' include macro-based generic Queue type used in earlier task

Declare_Queue(String) '' expand Queue type for Strings

Dim stringQueue As Queue(String)
With stringQueue  '' push some strings into the Queue
  .push("first")
  .push("second")
  .push("third")
  .push("fourth")
  .push("fifth")
End With
Print "Number of Strings in the Queue :" ; stringQueue.count
Print "Capacity of string Queue       :" ; stringQueue.capacity
Print
' now pop them
While Not stringQueue.empty
  Print stringQueue.pop(); " popped"
Wend
Print
Print "Number of Strings in the Queue :" ; stringQueue.count
Print "Capacity of string Queue       :" ; stringQueue.capacity   '' capacity should be unchanged
Print "Is Queue empty now             : "; stringQueue.empty
Print
Print "Press any key to quit"
Sleep


package main

import (
    "fmt"
    "queue"
)

func main() {
    q := new(queue.Queue)
    fmt.Println("empty?", q.Empty())

    x := "black"
    fmt.Println("push", x)
    q.Push(x)

    fmt.Println("empty?", q.Empty())
    r, ok := q.Pop()
    if ok {
        fmt.Println(r, "popped")
    } else {
        fmt.Println("pop failed")
    }

    var n int
    for _, x := range []string{"blue", "red", "green"} {
        fmt.Println("pushing", x)
        q.Push(x)
        n++
    }

    for i := 0; i < n; i++ {
        r, ok := q.Pop()
        if ok {
            fmt.Println(r, "popped")
        } else {
            fmt.Println("pop failed")
        }
    }
}


Prelude> :l fifo.hs
[1 of 1] Compiling Main             ( fifo.hs, interpreted )
Ok, modules loaded: Main.
*Main> let q = emptyFifo
*Main> isEmpty q
True
*Main> let q' = push q 1
*Main> isEmpty q'
False
*Main> let q'' = foldl push q' [2..4]
*Main> let (v,q''') = pop q''
*Main> v
Just 1
*Main> let (v',q'''') = pop q'''
*Main> v'
Just 2
*Main> let (v'',q''''') = pop q''''
*Main> v''
Just 3
*Main> let (v''',q'''''') = pop q'''''
*Main> v'''
Just 4
*Main> let (v'''',q''''''') = pop q''''''
*Main> v''''
Nothing


procedure main(arglist)
queue := []
write("Usage:\nqueue x x x - x - - - - -\n\t- pops elements\n\teverything else pushes")
write("Queue is:")
every x := !arglist do {
   case x of {
      "-"     : pop(queue)  | write("pop(empty) failed.")    # pop if the next arglist[i] is a -
      default : put(queue,x)                                 # push arglist[i]
      }
   if empty(queue) then writes("empty")
   else every writes(!queue," ")
   write()
   }
end

procedure empty(X)        #: fail if X is not empty
if *X = 0 then return
end


   queue=: conew 'fifo'
   isEmpty__queue ''
1
   push__queue 9
9
   push__queue 8
8
   push__queue 7
7
   isEmpty__queue ''
0
   pop__queue ''
9
   pop__queue ''
8
   pop__queue ''
7
   isEmpty__queue ''
1


import java.util.LinkedList;
import java.util.Queue;
...
Queue<Integer> queue = new LinkedList<Integer>();
System.out.println(queue.isEmpty());      // empty test - true
// queue.remove();       // would throw NoSuchElementException
queue.add(1);
queue.add(2);
queue.add(3);
System.out.println(queue);                // [1, 2, 3]
System.out.println(queue.remove());       // 1
System.out.println(queue);                // [2, 3]
System.out.println(queue.isEmpty());      // false


var f = new Array();
print(f.length);
f.push(1,2);         // can take multiple arguments
f.push(3);
f.shift();
f.shift();
print(f.length);
print(f.shift())
print(f.length == 0);
print(f.shift());


using DataStructures

queue = Queue(String)
@show enqueue!(queue, "foo")
@show enqueue!(queue, "bar")
@show dequeue!(queue) # -> foo
@show dequeue!(queue) # -> bar


// version 1.1.2

import java.util.*

fun main(args: Array<String>) {
    val q: Queue<Int> = ArrayDeque<Int>()
    (1..5).forEach { q.add(it) }
    println(q)
    println("Size of queue = ${q.size}")
    print("Removing: ")
    (1..3).forEach { print("${q.remove()} ") }
    println("\nRemaining in queue: $q")
    println("Head element is now ${q.element()}")
    q.clear()
    println("After clearing, queue is ${if(q.isEmpty()) "empty" else "not empty"}")
    try {
        q.remove()
    }
    catch (e: NoSuchElementException) {
        println("Can't remove elements from an empty queue")
    }
}


 push: queue->insert
  pop: queue->get
empty: queue->size == 0


make "fifo []
print empty? :fifo    ; true
queue "fifo 1
queue "fifo 2
queue "fifo 3
show :fifo            ; [1 2 3]
print dequeue "fifo   ; 1
show :fifo            ; [2 3]
print empty? :fifo    ; false


q = Queue.new()
Queue.push( q, 5 )
Queue.push( q, "abc" )

while not Queue.empty( q ) do
    print( Queue.pop( q ) )
end


Module CheckStackAsQueue {
	a=stack
	Stack a {
		Push 1, 2, 3
		Print number=3
		Print number=2
		Print number=1
		Print Empty=True
		Push "A", "B", "C"
		Print letter$="C"
		Print letter$="B"
		Print letter$="A"
		Print Empty=True
		Push 1,"OK"
	}
	Print Len(a)=2, StackItem(a, 2)=1, StackItem$(a, 1)="OK"
	Print StackType$(a, 1)="String", StackType$(a,2)="Number"
}
 CheckStackAsQueue


q := queue[new]();
queue[enqueue](q,1);
queue[enqueue](q,2);
queue[enqueue](q,3);
queue[empty](q);
>>>false
queue[dequeue](q);
>>>1
queue[dequeue](q);
>>>2
queue[dequeue](q);
>>>3
queue[empty](q);
>>>true


Empty[a_] := If[Length[a] == 0, True, False]
SetAttributes[Push, HoldAll]; Push[a_, elem_] := AppendTo[a, elem]
SetAttributes[Pop, HoldAllComplete]; Pop[a_] := If[EmptyQ[a], False, b = First[a]; Set[a, Most[a]]; b]

Queue = {}
-> {}
Empty[Queue]
-> True
Push[Queue, "1"]
-> {"1"}
EmptyQ[Queue]
->False
Pop[Queue]
->1
Pop[Queue]
->False


mutable q = Queue(); // or use immutable version as per Haskell example
def empty = q.IsEmpty(); // true at this point
q.Push(empty); // or Enqueue(), or Add()
def a = q.Pop(); // or Dequeue() or Take()


/* NetRexx */
options replace format comments java crossref savelog symbols nobinary

-- Queue Usage Demonstration Program -------------------------------------------
method main(args = String[]) public constant
  kew = RCQueueImpl()
  do
    say kew.pop()
  catch ex = IndexOutOfBoundsException
    say ex.getMessage
    say
  end

  melancholyDane = ''
  melancholyDane[0] = 4
  melancholyDane[1] = 'To be'
  melancholyDane[2] = 'or'
  melancholyDane[3] = 'not to be?'
  melancholyDane[4] = 'That is the question.'

  loop p_ = melancholyDane[0] to 1 by -1
    kew.push(melancholyDane[p_])
    end p_

  loop while \kew.empty
    popped = kew.pop
    say popped '\-'
    end
  say; say

  -- demonstrate stowing something other than a text string in the queue
  kew.push(melancholyDane)
  md = kew.pop
  loop l_ = 1 to md[0]
    say md[l_] '\-'
    end l_
  say

  return

-- Queue implementation --------------------------------------------------------
class RCQueueImpl
  properties private
    qqq = Deque

method RCQueueImpl() public
  qqq = ArrayDeque()
  return

method push(stuff) public
  qqq.push(stuff)
  return

method pop() public returns Rexx signals IndexOutOfBoundsException
  if qqq.isEmpty then signal IndexOutOfBoundsException('The queue is empty')
  return Rexx qqq.pop()

method empty() public binary returns boolean
  return qqq.isEmpty

method isTrue public constant binary returns boolean
  return 1 == 1

method isFalse public constant binary returns boolean
  return \isTrue


import deques

var queue = initDeque[int]()

queue.addLast(26)
queue.addLast(99)
queue.addLast(2)
echo "Queue size: ", queue.len()
echo "Popping: ", queue.popFirst()
echo "Popping: ", queue.popFirst()
echo "Popping: ", queue.popFirst()
echo "Popping: ", queue.popFirst()


class Test {
  function : Main(args : String[]) ~ Nil {
    q := Struct.IntQueue->New();
    q->Add(1);
    q->Add(2);
    q->Add(3);

    q->Remove()->PrintLine();
    q->Remove()->PrintLine();
    q->Remove()->PrintLine();

    q->IsEmpty()->PrintLine();
  }
}


# let q = Queue.create ();;
val q : '_a Queue.t = <abstr>
# Queue.is_empty q;;
- : bool = true
# Queue.add 1 q;;
- : unit = ()
# Queue.is_empty q;;
- : bool = false
# Queue.add 2 q;;
- : unit = ()
# Queue.add 3 q;;
- : unit = ()
# Queue.peek q;;
- : int = 1
# Queue.length q;;
- : int = 3
# Queue.iter (Printf.printf "%d, ") q; print_newline ();;
1, 2, 3,
- : unit = ()
# Queue.take q;;
- : int = 1
# Queue.take q;;
- : int = 2
# Queue.peek q;;
- : int = 3
# Queue.length q;;
- : int = 1
# Queue.add 4 q;;
- : unit = ()
# Queue.take q;;
- : int = 3
# Queue.peek q;;
- : int = 4
# Queue.take q;;
- : int = 4
# Queue.is_empty q;;
- : bool = true


: testQueue
| q i |
   Queue new ->q
   20 loop: i [ i q push ]
   while ( q empty not ) [ q pop . ] ;


q = .queue~new      -- create an instance
q~queue(3)          -- adds to the end, but this is at the front
q~push(1)           -- push on the front
q~queue(2)          -- add to the end
say q~pull q~pull q~pull q~isempty  -- should display all and be empty


declare
  [Queue] = {Link ['x-oz://system/adt/Queue.ozf']}
  MyQueue = {Queue.new}
in
  {MyQueue.isEmpty} = true
  {MyQueue.put foo}
  {MyQueue.put bar}
  {MyQueue.put baz}
  {MyQueue.isEmpty} = false
  {Show {MyQueue.get}}  %% foo
  {Show {MyQueue.get}}  %% bar
  {Show {MyQueue.get}}  %% baz


@queue = (); # we will simulate a queue in a array

push @queue, (1..5); # enqueue numbers from 1 to 5

print shift @queue,"\n"; # dequeue

print "array is empty\n" unless @queue; # is empty ?

print $n while($n = shift @queue); # dequeue all
print "\n";
print "array is empty\n" unless @queue; # is empty ?


with javascript_semantics
printf(1,"empty:%t\n",empty())          -- true
push_item(5)
printf(1,"empty:%t\n",empty())          -- false
push_item(6)
printf(1,"pop_item:%v\n",pop_item())    -- 5
printf(1,"pop_item:%v\n",pop_item())    -- 6
printf(1,"empty:%t\n",empty())          -- true


<?php
$queue = new SplQueue;
echo $queue->isEmpty() ? 'true' : 'false', "\n";  // empty test - returns true
// $queue->dequeue();                             // would raise RuntimeException
$queue->enqueue(1);
$queue->enqueue(2);
$queue->enqueue(3);
echo $queue->dequeue(), "\n";                     // returns 1
echo $queue->isEmpty() ? 'true' : 'false', "\n";  // returns false
?>


(println (fifo 'Queue))    # Retrieve the number '1'
(println (fifo 'Queue))    # Retrieve an internal symbol 'abc'
(println (fifo 'Queue))    # Retrieve a transient symbol "abc"
(println (fifo 'Queue))    # and a list (abc)
(println (fifo 'Queue))    # Queue is empty -> NIL


test: proc options (main);

   /* To implement a queue. */
   define structure
      1 node,
         2 value fixed,
         2 link handle(node);
   declare (head, tail, t) handle (node);
   declare null builtin;
   declare i fixed binary;

   head, tail = bind(:node, null:);

   do i = 1 to 10; /* Add ten items to the tail of the queue. */
      if head = bind(:node, null:) then
         do;
            head,tail = new(:node:);
            get list (head => value);
            put skip list (head => value);
            head => link = bind(:node, null:); /* A NULL link */
         end;
      else
         do;
            t = new(:node:);
            tail => link = t; /* Point the tail to the new node. */
            tail = t;
            tail => link = bind(:node, null:); /* Set the tail link to NULL */
            get list (tail => value) copy;
            put skip list (tail => value);
         end;
   end;

   /* Pop all the items in the queue. */
   put skip list ('The queue has:');
   do while (head ^= bind(:node, null:));
      put skip list (head => value);
      head = head => link;
   end;
end test;


[System.Collections.ArrayList]$queue = @()
# isEmpty?
if ($queue.Count -eq 0) {
    "isEmpty? result : the queue is empty"
} else {
    "isEmpty? result : the queue is not empty"
}
"the queue contains : $queue"
$queue += 1                    # push
"push result : $queue"
$queue += 2                    # push
$queue += 3                    # push
"push result : $queue"

$queue.RemoveAt(0)             # pop
"pop result : $queue"

$queue.RemoveAt(0)             # pop
"pop result : $queue"

if ($queue.Count -eq 0) {
    "isEmpty? result : the queue is empty"
} else {
    "isEmpty? result : the queue is not empty"
}
"the queue contains : $queue"


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% definitions of queue
empty(U-V) :-
    unify_with_occurs_check(U, V).

push(Queue, Value, NewQueue) :-
    append_dl(Queue, [Value|X]-X, NewQueue).

pop([X|V]-U, X, V-U) :-
    \+empty([X|V]-U).

append_dl(X-Y, Y-Z, X-Z).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% use of queue
queue :-
    % create an empty queue
    empty(Q),
    format('Create queue ~w~n~n', [Q]),

    % add numbers 1 and 2
    write('Add numbers 1 and 2 : '),
    push(Q, 1, Q1),
    push(Q1, 2, Q2),

    % display queue
    format('~w~n~n', [Q2]),

    % pop element
    pop(Q2, V, Q3),

    % display results
    format('Pop : Value ~w Queue : ~w~n~n', [V, Q3]),

    % test the queue
    write('Test of the queue : '),
    (   empty(Q3) -> writeln('Queue empy'); writeln('Queue not empty')), nl,

    % pop the elements
    write('Pop the queue : '),
    pop(Q3, V1, Q4),
    format('Value ~w Queue : ~w~n~n', [V1, Q4]),

    write('Pop the queue : '),
    pop(Q4, _V, _Q5).


NewList MyStack()

Procedure Push(n)
  Shared MyStack()
  LastElement(MyStack())
  AddElement(MyStack())
  MyStack()=n
EndProcedure

Procedure Pop()
  Shared MyStack()
  Protected n
  If FirstElement(MyStack())  ; e.g. Stack not empty
    n=MyStack()
    DeleteElement(MyStack(),1)
  EndIf
  ProcedureReturn n
EndProcedure

Procedure Empty()
  Shared MyStack()
  If  ListSize(MyStack())=0
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

;----   Example of implementation ----
Push(3)
Push(1)
Push(4)
Push(1)
Push(5)
While Not Empty()
  Debug Pop()
Wend


import Queue
my_queue = Queue.Queue()
my_queue.put("foo")
my_queue.put("bar")
my_queue.put("baz")
print my_queue.get()  # foo
print my_queue.get()  # bar
print my_queue.get()  # baz


[ [] ]          is queue  (     --> q   )

[ nested join ] is push   ( q x --> q   )

[ behead ]      is pop    (   q --> q x )

[ [] = ]        is empty? (   q --> b   )


#lang racket

(require data/queue)

(define queue (make-queue))

(enqueue! queue 'black)
(queue-empty? queue) ; #f

(enqueue! queue 'red)
(enqueue! queue 'green)

(dequeue! queue) ; 'black
(dequeue! queue) ; 'red
(dequeue! queue) ; 'green

(queue-empty? queue) ; #t


push (aka enqueue) -- @list.push
pop (aka dequeue)  -- @list.shift
empty              -- [email protected]


; Create and populate a FIFO:

q: make fifo []
q/push 'a
q/push 2
q/push USD$12.34              ; Did I mention that REBOL has 'money!' datatype?
q/push [Athos Porthos Aramis] ; List elements pushed on one by one.
q/push [[Huey Dewey Lewey]]   ; This list is preserved as a list.

; Dump it out, with narrative:

print rejoin ["Queue is "  either q/empty [""]["not "]  "empty."]
while [not q/empty][print ["  " q/pop]]
print rejoin ["Queue is "  either q/empty [""]["not "]  "empty."]
print ["Trying to pop an empty queue yields:" q/pop]


/*REXX program demonstrates four  queueing  operations:   push,  pop,  empty,  query.   */
say '══════════════════════════════════ Pushing five values to the stack.'
        do j=1  for 4                            /*a  DO  loop to  PUSH  four values.   */
        call push  j * 10                        /*PUSH   (aka:   enqueue to the stack).*/
        say 'pushed value:'    j * 10            /*echo the pushed value.               */
        if j\==3  then iterate                   /*Not equal 3?   Then use a new number.*/
        call push                                /*PUSH   (aka:   enqueue to the stack).*/
        say 'pushed a "null" value.'             /*echo what was  pushed  to the stack. */
        end   /*j*/
say '══════════════════════════════════ Quering the stack  (number of entries).'
        say  queued()  ' entries in the stack.'
say '══════════════════════════════════ Popping all values from the stack.'
        do k=1  while  \empty()                  /*EMPTY (returns  TRUE  [1]  if empty).*/
        call pop                                 /*POP   (aka:  dequeue from the stack).*/
        say k': popped value='  result           /*echo the popped value.               */
        end   /*k*/
say '══════════════════════════════════ The stack is now empty.'
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
push:   queue arg(1);              return        /*(The  REXX  QUEUE   is FIFO.)        */
pop:    procedure;  parse pull x;  return x      /*REXX   PULL   removes a stack item.  */
empty:  return queued()==0                       /*returns the status of the stack.     */


use std::collections::VecDeque;

fn main() {
    let mut queue = VecDeque::new();
    queue.push_back("Hello");
    queue.push_back("World");
    while let Some(item) = queue.pop_front() {
        println!("{}", item);
    }

    if queue.is_empty() {
        println!("Yes, it is empty!");
    }
}


val q=scala.collection.mutable.Queue[Int]()
println("isEmpty = " + q.isEmpty)
try{q dequeue} catch{case _:java.util.NoSuchElementException => println("dequeue(empty) failed.")}
q enqueue 1
q enqueue 2
q enqueue 3
println("queue   = " + q)
println("front   = " + q.front)
println("dequeue = " + q.dequeue)
println("dequeue = " + q.dequeue)
println("isEmpty = " + q.isEmpty)


var f = FIFO();
say f.empty;        # true
f.push('foo');
f.push('bar', 'baz');
say f.pop;          # foo
say f.empty;        # false

var g = FIFO('xxx', 'yyy');
say g.pop;          # xxx
say f.pop;          # bar


- open Fifo;
opening Fifo
  datatype 'a fifo = ...
  exception Dequeue
  val empty : 'a fifo
  val isEmpty : 'a fifo -> bool
  val enqueue : 'a fifo * 'a -> 'a fifo
  val dequeue : 'a fifo -> 'a fifo * 'a
  val next : 'a fifo -> ('a * 'a fifo) option
  val delete : 'a fifo * ('a -> bool) -> 'a fifo
  val head : 'a fifo -> 'a
  val peek : 'a fifo -> 'a option
  val length : 'a fifo -> int
  val contents : 'a fifo -> 'a list
  val app : ('a -> unit) -> 'a fifo -> unit
  val map : ('a -> 'b) -> 'a fifo -> 'b fifo
  val foldl : ('a * 'b -> 'b) -> 'b -> 'a fifo -> 'b
  val foldr : ('a * 'b -> 'b) -> 'b -> 'a fifo -> 'b
- val q = empty;
val q = Q {front=[],rear=[]} : 'a fifo
- isEmpty q;
val it = true : bool
- val q' = enqueue (q, 1);
val q' = Q {front=[],rear=[1]} : int fifo
- isEmpty q';
val it = false : bool
- val q'' = List.foldl (fn (x, q) => enqueue (q, x)) q' [2, 3, 4];
val q'' = Q {front=[],rear=[4,3,2,1]} : int fifo
- peek q'';
val it = SOME 1 : int option
- length q'';
val it = 4 : int
- contents q'';
val it = [1,2,3,4] : int list
- val (q''', v) = dequeue q'';
val q''' = Q {front=[2,3,4],rear=[]} : int fifo
val v = 1 : int
- val (q'''', v') = dequeue q''';
val q'''' = Q {front=[3,4],rear=[]} : int fifo
val v' = 2 : int
- val (q''''', v'') = dequeue q'''';
val q''''' = Q {front=[4],rear=[]} : int fifo
val v'' = 3 : int
- val (q'''''', v''') = dequeue q''''';
val q'''''' = Q {front=[],rear=[]} : int fifo
val v''' = 4 : int
- isEmpty q'''''';
val it = true : bool


set Q [list]
empty Q     ;# ==> 1 (true)
push Q foo
empty Q     ;# ==> 0 (false)
push Q bar
peek Q      ;# ==> foo
pop Q       ;# ==> foo
peek Q      ;# ==> bar


# any valid variable name can be used as a queue without initialization

queue_empty foo && echo foo is empty || echo foo is not empty

queue_push foo bar
queue_push foo baz
queue_push foo "element with spaces"

queue_empty foo && echo foo is empty || echo foo is not empty

print "peek: $(queue_peek foo)"; queue_pop foo
print "peek: $(queue_peek foo)"; queue_pop foo
print "peek: $(queue_peek foo)"; queue_pop foo
print "peek: $(queue_peek foo)"; queue_pop foo


Public Sub fifo()
    push "One"
    push "Two"
    push "Three"
    Debug.Print pop, pop, pop, empty_
End Sub


q <- (queue)
empty? q
=> 1
enq 1 q
empty? q
=> nil
enq 2 q
len q
=> 2
deq q
len q
=> 1


import "/queue" for Queue

var q = Queue.new()
q.push(1)
q.push(2)
System.print("Queue contains %(q)")
System.print("Number of elements in queue = %(q.count)")
var item = q.pop()
System.print("'%(item)' popped from the queue")
System.print("First element is now %(q.peek())")
q.clear()
System.print("Queue cleared")
System.print("Is queue now empty? %((q.isEmpty) ? "yes" : "no")")


include c:\cxpl\codes;
def Size=8;
int Fifo(Size);
int In, Out;            \fill and empty indexes into Fifo

proc Push(A);           \Add integer A to queue
int  A;                 \(overflow not detected)
[Fifo(In):= A;
In:= In+1;
if In >= Size then In:= 0;
];

func Pop;               \Return first integer in queue
int  A;
[if Out=In then                   \if popping empty queue
    [Text(0, "Error");  exit 1];  \ then exit program with error code 1
A:= Fifo(Out);
Out:= Out+1;
if Out >= Size then Out:= 0;
return A;
];

func Empty;             \Return 'true' if queue is empty
return In = Out;

[In:= 0;  Out:= 0;
Push(0);
Text(0, if Empty then "true" else "false");  CrLf(0);
IntOut(0, Pop);  CrLf(0);
Push(1);
Push(2);
Push(3);
IntOut(0, Pop);  CrLf(0);
IntOut(0, Pop);  CrLf(0);
IntOut(0, Pop);  CrLf(0);
Text(0, if Empty then "true" else "false");  CrLf(0);

\A 256-byte queue is built in as device 8:
OpenI(8);  OpenO(8);
ChOut(8, ^0);                   \push
ChOut(0, ChIn(8));  CrLf(0);    \pop
ChOut(8, ^1);                   \push
ChOut(8, ^2);                   \push
ChOut(8, ^3);                   \push
ChOut(0, ChIn(8));  CrLf(0);    \pop
ChOut(0, ChIn(8));  CrLf(0);    \pop
ChOut(0, ChIn(8));  CrLf(0);    \pop
]


sub push(x$)
    queue$ = queue$ + x$ + "#"
end sub

sub pop$()
    local i, r$

    if queue$ <> "" then
        i = instr(queue$, "#")
        if i then
            r$ = left$(queue$, i-1)
            stack$ = right$(queue$, len(queue$) - i)
        else
            r$ = queue$
            queue$ = ""
        end if
        return r$
    else
        print "--Queue is empty--"
    end if
end sub

sub empty()
    return queue$ = ""
end sub

// ======== test ========

for n = 3 to 5
    print "Push ", n : push(str$(n))
next

print "Pop ", pop$()

print "Push ", 6 : push(str$(6))

while(not empty())
    print "Pop ", pop$()
wend

print "Pop ", pop$()


q:=Queue();
q.empty();   //-->True
q.push(1,2,3);
q.pop();     //-->1
q.empty();   //-->False
q.pop();q.pop();q.pop(); //-->IndexError thrown


F partition(&vector, left, right, pivotIndex)
   V pivotValue = vector[pivotIndex]
   swap(&vector[pivotIndex], &vector[right])
   V storeIndex = left
   L(i) left .< right
      I vector[i] < pivotValue
         swap(&vector[storeIndex], &vector[i])
         storeIndex++
   swap(&vector[right], &vector[storeIndex])
   R storeIndex

F _select(&vector, =left, =right, =k)
   ‘Returns the k-th smallest, (k >= 0), element of vector within vector[left:right+1] inclusive.’
   L
      V pivotIndex = (left + right) I/ 2
      V pivotNewIndex = partition(&vector, left, right, pivotIndex)
      V pivotDist = pivotNewIndex - left
      I pivotDist == k
         R vector[pivotNewIndex]
      E I k < pivotDist
         right = pivotNewIndex - 1
      E
         k -= pivotDist + 1
         left = pivotNewIndex + 1

F select(&vector, k)
   ‘
    Returns the k-th smallest, (k >= 0), element of vector within vector[left:right+1].
    left, right default to (0, len(vector) - 1) if omitted
   ’
   V left = 0
   V lv1 = vector.len - 1
   V right = lv1
   assert(!vector.empty & k >= 0, ‘Either null vector or k < 0 ’)
   assert(left C 0 .. lv1, ‘left is out of range’)
   assert(right C left .. lv1, ‘right is out of range’)
   R _select(&vector, left, right, k)

V v = [9, 8, 7, 6, 5, 0, 1, 2, 3, 4]
print((0.<10).map(i -> select(&:v, i)))


PROC Swap(BYTE ARRAY tab INT i,j)
  BYTE tmp

  tmp=tab(i) tab(i)=tab(j) tab(j)=tmp
RETURN

BYTE FUNC QuickSelect(BYTE ARRAY tab INT count,index)
  INT px,i,j,k
  BYTE pv

  DO
    px=count/2
    pv=tab(px)
    Swap(tab,px,count-1)

    i=0
    FOR j=0 TO count-2
    DO
      IF tab(j)<pv THEN
        Swap(tab,i,j)
        i==+1
      FI
    OD

    IF i=index THEN
      RETURN (pv)
    ELSEIF i>index THEN
      ;left part of tab from 0 to i-1
      count=i
    ELSE
      Swap(tab,i,count-1)
      ;right part of tab from i+1 to count-1
      tab==+(i+1)
      count==-(i+1)
      index==-(i+1)
    FI
  OD
RETURN (0)

PROC Main()
  DEFINE COUNT="10"
  BYTE ARRAY data=[9 8 7 6 5 0 1 2 3 4],tab(COUNT)
  BYTE i,res

  FOR i=0 TO COUNT-1
  DO
    MoveBlock(tab,data,COUNT)
    res=QuickSelect(tab,COUNT,i)
    PrintB(res) Put(32)
  OD
RETURN


----------------------------------------------------------------------

with Ada.Numerics.Float_Random;
with Ada.Text_IO;

procedure quickselect_task
is

  use Ada.Numerics.Float_Random;
  use Ada.Text_IO;

  gen : Generator;

----------------------------------------------------------------------
--
-- procedure partition
--
-- Partitioning a subarray into two halves: one with elements less
-- than or equal to a pivot, the other with elements greater than or
-- equal to a pivot.
--

  generic
    type T is private;
    type T_Array is array (Natural range <>) of T;
  procedure partition
   (less_than : access function
     (x, y : T)
      return Boolean;
    pivot           : in     T;
    i_first, i_last : in     Natural;
    arr             : in out T_Array;
    i_pivot         :    out Natural);

  procedure partition
   (less_than : access function
     (x, y : T)
      return Boolean;
    pivot           : in     T;
    i_first, i_last : in     Natural;
    arr             : in out T_Array;
    i_pivot         :    out Natural)
  is
    i, j : Integer;
    temp : T;
  begin

    i := Integer (i_first) - 1;
    j := i_last + 1;

    while i /= j loop
      -- Move i so everything to the left of i is less than or equal
      -- to the pivot.
      i := i + 1;
      while i /= j and then not less_than (pivot, arr (i)) loop
        i := i + 1;
      end loop;

      -- Move j so everything to the right of j is greater than or
      -- equal to the pivot.
      if i /= j then
        j := j - 1;
        while i /= j and then not less_than (arr (j), pivot) loop
          j := j - 1;
        end loop;
      end if;

      -- Swap entries.
      temp    := arr (i);
      arr (i) := arr (j);
      arr (j) := temp;
    end loop;

    i_pivot := i;

  end partition;

----------------------------------------------------------------------
--
-- procedure quickselect
--
-- Quickselect with a random pivot. Returns the (k+1)st element of a
-- subarray, according to the given order predicate. Also rearranges
-- the subarray so that anything "less than" the (k+1)st element is to
-- the left of it, and anything "greater than" it is to its right.
--
-- I use a random pivot to get O(n) worst case *expected* running
-- time. Code using a random pivot is easy to write and read, and for
-- most purposes comes close enough to a criterion set by Scheme's
-- SRFI-132: "Runs in O(n) time." (See
-- https://srfi.schemers.org/srfi-132/srfi-132.html)
--
-- Of course we are not bound here by SRFI-132, but still I respect
-- it as a guide.
--
-- A "median of medians" pivot gives O(n) running time, but
-- quickselect with such a pivot is a complicated algorithm requiring
-- many comparisons of array elements. A random number generator, by
-- contrast, requires no comparisons of array elements.
--

  generic
    type T is private;
    type T_Array is array (Natural range <>) of T;
  procedure quickselect
   (less_than : access function
     (x, y : T)
      return Boolean;
    i_first, i_last    : in     Natural;
    k                  : in     Natural;
    arr                : in out T_Array;
    the_element        :    out T;
    the_elements_index :    out Natural);

  procedure quickselect
   (less_than : access function
     (x, y : T)
      return Boolean;
    i_first, i_last    : in     Natural;
    k                  : in     Natural;
    arr                : in out T_Array;
    the_element        :    out T;
    the_elements_index :    out Natural)
  is
    procedure T_partition is new partition (T, T_Array);

    procedure qselect
     (less_than : access function
       (x, y : T)
        return Boolean;
      i_first, i_last    : in     Natural;
      k                  : in     Natural;
      arr                : in out T_Array;
      the_element        :    out T;
      the_elements_index :    out Natural)
    is
      i, j    : Natural;
      i_pivot : Natural;
      i_final : Natural;
      pivot   : T;
    begin

      i := i_first;
      j := i_last;

      while i /= j loop
        i_pivot :=
         i + Natural (Float'Floor (Random (gen) * Float (j - i + 1)));
        i_pivot := Natural'Min (j, i_pivot);
        pivot   := arr (i_pivot);

        -- Move the last element to where the pivot had been. Perhaps
        -- the pivot was already the last element, of course. In any
        -- case, we shall partition only from i to j - 1.
        arr (i_pivot) := arr (j);

        -- Partition the array in the range i .. j - 1, leaving out
        -- the last element (which now can be considered garbage).
        T_partition (less_than, pivot, i, j - 1, arr, i_final);

        -- Now everything that is less than the pivot is to the left
        -- of I_final.

        -- Put the pivot at i_final, moving the element that had been
        -- there to the end. If i_final = j, then this element is
        -- actually garbage and will be overwritten with the pivot,
        -- which turns out to be the greatest element. Otherwise, the
        -- moved element is not less than the pivot and so the
        -- partitioning is preserved.
        arr (j)       := arr (i_final);
        arr (i_final) := pivot;

        -- Compare i_final and k, to see what to do next.
        if i_final < k then
          i := i_final + 1;
        elsif k < i_final then
          j := i_final - 1;
        else
          -- Exit the loop.
          i := i_final;
          j := i_final;
        end if;
      end loop;

      the_element        := arr (i);
      the_elements_index := i;

    end qselect;
  begin
    -- Adjust k for the subarray's position.
    qselect
     (less_than, i_first, i_last, k + i_first, arr, the_element,
      the_elements_index);
  end quickselect;

----------------------------------------------------------------------

  type Integer_Array is array (Natural range <>) of Integer;

  procedure integer_quickselect is new quickselect
   (Integer, Integer_Array);

  procedure print_kth
   (less_than : access function
     (x, y : Integer)
      return Boolean;
    k               : in     Positive;
    i_first, i_last : in     Integer;
    arr             : in out Integer_Array)
  is
    copy_of_arr        : Integer_Array (0 .. i_last);
    the_element        : Integer;
    the_elements_index : Natural;
  begin
    for j in 0 .. i_last loop
      copy_of_arr (j) := arr (j);
    end loop;
    integer_quickselect
     (less_than, i_first, i_last, k - 1, copy_of_arr, the_element,
      the_elements_index);
    Put (Integer'Image (the_element));
  end print_kth;

----------------------------------------------------------------------

  example_numbers : Integer_Array := (9, 8, 7, 6, 5, 0, 1, 2, 3, 4);

  function lt
   (x, y : Integer)
    return Boolean
  is
  begin
    return (x < y);
  end lt;

  function gt
   (x, y : Integer)
    return Boolean
  is
  begin
    return (x > y);
  end gt;

begin
  Put ("With < as order predicate: ");
  for k in 1 .. 10 loop
    print_kth (lt'Access, k, 0, 9, example_numbers);
  end loop;
  Put_Line ("");
  Put ("With > as order predicate: ");
  for k in 1 .. 10 loop
    print_kth (gt'Access, k, 0, 9, example_numbers);
  end loop;
  Put_Line ("");
end quickselect_task;

----------------------------------------------------------------------


BEGIN
    # returns the kth lowest element of list using the quick select algorithm #
    PRIO QSELECT = 1;
    OP   QSELECT = ( INT k, REF[]INT list )INT:
         IF LWB list > UPB list THEN
             # empty list #
             0
         ELSE
             # non-empty list #
             # partitions the subset of list from left to right #
             PROC partition = ( REF[]INT list, INT left, right, pivot index )INT:
                  BEGIN
                      # swaps elements a and b in list #
                      PROC swap = ( REF[]INT list, INT a, b )VOID:
                           BEGIN
                               INT t = list[ a ];
                               list[ a ] := list[ b ];
                               list[ b ] := t
                           END # swap # ;
                      INT pivot value = list[ pivot index ];
                      swap( list, pivot index, right );
                      INT store index := left;
                      FOR i FROM left TO right - 1 DO
                          IF list[ i ] < pivot value THEN
                              swap( list, store index, i );
                              store index +:= 1
                          FI
                      OD;
                      swap( list, right, store index );
                      store index
                  END # partition # ;
             INT  left  := LWB list, right := UPB list, result := 0;
             BOOL found := FALSE;
             WHILE NOT found DO
                 IF left = right THEN
                     result := list[ left ];
                     found := TRUE
                 ELSE
                     INT pivot index = partition( list, left, right, left + ENTIER ( ( random * ( right - left ) + 1 ) ) );
                     IF k = pivot index THEN
                         result := list[ k ];
                         found := TRUE
                     ELIF k < pivot index THEN
                         right := pivot index - 1
                     ELSE
                         left  := pivot index + 1
                     FI
                 FI
             OD;
             result
         FI # QSELECT # ;
    # test cases #
    FOR i TO 10 DO
        [ 1 : 10 ]INT test := []INT( 9, 8, 7, 6, 5, 0, 1, 2, 3, 4 );
        print( ( whole( i, -2 ), ": ", whole( i QSELECT test, -3 ), newline ) )
    OD
END


on quickselect(theList, l, r, k)
    script o
        property lst : theList's items -- Shallow copy.
    end script

    repeat
        -- Median-of-3 pivot selection.
        set leftValue to item l of o's lst
        set rightValue to item r of o's lst
        set pivot to item ((l + r) div 2) of o's lst
        set leftGreaterThanRight to (leftValue > rightValue)
        if (leftValue > pivot) then
            if (leftGreaterThanRight) then
                if (rightValue > pivot) then set pivot to rightValue
            else
                set pivot to leftValue
            end if
        else if (pivot > rightValue) then
            if (leftGreaterThanRight) then
                set pivot to leftValue
            else
                set pivot to rightValue
            end if
        end if

        -- Initialise pivot store indices and swap the already compared outer values here if necessary.
        set pLeft to l - 1
        set pRight to r + 1
        if (leftGreaterThanRight) then
            set item r of o's lst to leftValue
            set item l of o's lst to rightValue
            if (leftValue = pivot) then
                set pRight to r
            else if (rightValue = pivot) then
                set pLeft to l
            end if
        else
            if (leftValue = pivot) then set pLeft to l
            if (rightValue = pivot) then set pRight to r
        end if

        -- Continue three-way partitioning.
        set i to l + 1
        set j to r - 1
        repeat until (i > j)
            set leftValue to item i of o's lst
            repeat while (leftValue < pivot)
                set i to i + 1
                set leftValue to item i of o's lst
            end repeat

            set rightValue to item j of o's lst
            repeat while (rightValue > pivot)
                set j to j - 1
                set rightValue to item j of o's lst
            end repeat

            if (j > i) then
                if (leftValue = pivot) then
                    set pRight to pRight - 1
                    if (pRight > j) then
                        set leftValue to item pRight of o's lst
                        set item pRight of o's lst to pivot
                    end if
                end if
                if (rightValue = pivot) then
                    set pLeft to pLeft + 1
                    if (pLeft < i) then
                        set rightValue to item pLeft of o's lst
                        set item pLeft of o's lst to pivot
                    end if
                end if
                set item j of o's lst to leftValue
                set item i of o's lst to rightValue
            else if (i > j) then
                exit repeat
            end if

            set i to i + 1
            set j to j - 1
        end repeat
        -- Swap stored pivot(s) into a central partition.
        repeat with p from l to pLeft
            if (j > pLeft) then
                set item p of o's lst to item j of o's lst
                set item j of o's lst to pivot
                set j to j - 1
            else
                set j to p - 1
                exit repeat
            end if
        end repeat
        repeat with p from r to pRight by -1
            if (i < pRight) then
                set item p of o's lst to item i of o's lst
                set item i of o's lst to pivot
                set i to i + 1
            else
                set i to p + 1
                exit repeat
            end if
        end repeat

        -- If k's in either of the outer partitions, repeat for that partition. Othewise return the item in slot k.
        if (k ≥ i) then
            set l to i
        else if (k ≤ j) then
            set r to j
        else
            return item k of o's lst
        end if
    end repeat
end quickselect

-- Task code:
set theVector to {9, 8, 7, 6, 5, 0, 1, 2, 3, 4}
set selected to {}
set vectorLength to (count theVector)
repeat with i from 1 to vectorLength
    set end of selected to quickselect(theVector, 1, vectorLength, i)
end repeat
return selected


quickselect: function [a k][
    arr: new a
    while ø [
        indx: random 0 (size arr)-1
        pivot: arr\[indx]
        remove 'arr .index indx
        left: select arr 'item -> item<pivot
        right: select arr 'item -> item>pivot

        case [k]
            when? [= size left]-> return pivot
            when? [< size left]-> arr: new left
            else [
                k: (k - size left) - 1
                arr: new right
            ]
    ]
]

v: [9 8 7 6 5 0 1 2 3 4]

print map 0..(size v)-1 'i ->
    quickselect v i


(*------------------------------------------------------------------*)
(*

  For linear linked lists, using a random pivot:

    * stable three-way "separation" (a variant of quickselect)
    * quickselect
    * stable quicksort

  Also a couple of routines for splitting lists according to a
  predicate.

  Linear list operations are destructive but may avoid doing many
  unnecessary allocations. Also they do not require a garbage
  collector.

*)

#include "share/atspre_staload.hats"

staload UN = "prelude/SATS/unsafe.sats"

#define NIL list_vt_nil ()
#define ::  list_vt_cons

(*------------------------------------------------------------------*)
(* A simple linear congruential generator for pivot selection.      *)

(* The multiplier lcg_a comes from Steele, Guy; Vigna, Sebastiano (28
   September 2021). "Computationally easy, spectrally good multipliers
   for congruential pseudorandom number generators".
   arXiv:2001.05304v3 [cs.DS] *)
macdef lcg_a = $UN.cast{uint64} 0xf1357aea2e62a9c5LLU

(* lcg_c must be odd. *)
macdef lcg_c = $UN.cast{uint64} 0xbaceba11beefbeadLLU

var seed : uint64 = $UN.cast 0
val p_seed = [email protected] seed

fn
random_double () :<!wrt> double =
  let
    val (pf, fpf | p_seed) = $UN.ptr0_vtake{uint64} p_seed
    val old_seed = ptr_get<uint64> (pf | p_seed)

    (* IEEE "binary64" or "double" has 52 bits of precision. We will
       take the high 48 bits of the seed and divide it by 2**48, to
       get a number 0.0 <= randnum < 1.0 *)
    val high_48_bits = $UN.cast{double} (old_seed >> 16)
    val divisor = $UN.cast{double} (1LLU << 48)
    val randnum = high_48_bits / divisor

    (* The following operation is modulo 2**64, by virtue of standard
       C behavior for uint64_t. *)
    val new_seed = (lcg_a * old_seed) + lcg_c

    val () = ptr_set<uint64> (pf | p_seed, new_seed)
    prval () = fpf pf
  in
    randnum
  end

(*------------------------------------------------------------------*)

(* Destructive split into two lists: a list of leading elements that
   satisfy a predicate, and the tail of that split. (This is similar
   to "span!" in SRFI-1.) *)
extern fun {a : [email protected]}
list_vt_span {n    : int}
             (pred : &((&a) -<cloptr1> bool),
              lst  : list_vt (a, n))
    : [n1, n2 : nat | n1 + n2 == n]
      @(list_vt (a, n1),
        list_vt (a, n2))

(* Destructive, stable partition into elements less than the pivot,
   elements equal to the pivot, and elements greater than the
   pivot. *)
extern fun {a : [email protected]}
list_vt_three_way_partition
          {n       : int}
          (compare : &((&a, &a) -<cloptr1> int),
           pivot   : &a,
           lst     : list_vt (a, n))
    : [n1, n2, n3 : nat | n1 + n2 + n3 == n]
      @(list_vt (a, n1),
        list_vt (a, n2),
        list_vt (a, n3))

(* Destructive, stable partition into elements less than the kth least
   element, elements equal to it, and elements greater than it. *)
extern fun {a : [email protected]}
list_vt_three_way_separation
          {n, k    : int | 0 <= k; k < n}
          (compare : &((&a, &a) -<cloptr1> int),
           k       : int k,
           lst     : list_vt (a, n))
    : [n1, n2, n3 : nat | n1 + n2 + n3 == n;
                          n1 <= k; k < n1 + n2]
      @(int n1, list_vt (a, n1),
        int n2, list_vt (a, n2),
        int n3, list_vt (a, n3))

(* Destructive quickselect for linear elements. *)
extern fun {a : [email protected]}
list_vt_select_linear
          {n, k    : int | 0 <= k; k < n}
          (compare : &((&a, &a) -<cloptr1> int),
           k       : int k,
           lst     : list_vt (a, n)) : a
extern fun {a : [email protected]}
list_vt_select_linear$clear (x : &a >> a?) : void

(* Destructive quickselect for non-linear elements. *)
extern fun {a : [email protected]}
list_vt_select
          {n, k    : int | 0 <= k; k < n}
          (compare : &((&a, &a) -<cloptr1> int),
           k       : int k,
           lst     : list_vt (a, n)) : a

(* Stable quicksort. Also returns the length. *)
extern fun {a : [email protected]}
list_vt_stable_sort
          {n       : int}
          (compare : &((&a, &a) -<cloptr1> int),
           lst     : list_vt (a, n))
    : @(int n, list_vt (a, n))

(*------------------------------------------------------------------*)

implement {a}
list_vt_span {n} (pred, lst) =
  let
    fun
    loop {n      : nat} .<n>.
         (pred   : &((&a) -<cloptr1> bool),
          cursor : &list_vt (a, n) >> list_vt (a, m),
          tail   : &List_vt a? >> list_vt (a, n - m))
        : #[m : nat | m <= n] void =
      case+ cursor of
      | NIL => tail := NIL
      | @ elem :: rest =>
        if pred (elem) then
          (* elem satisfies the predicate. Move the cursor to the next
             cons-pair in the list. *)
          let
            val () = loop {n - 1} (pred, rest, tail)
            prval () = [email protected] cursor
          in
          end
        else
          (* elem does not satisfy the predicate. Split the list at
             the cursor. *)
          let
            prval () = [email protected] cursor
            val () = tail := cursor
            val () = cursor := NIL
          in
          end

    prval () = lemma_list_vt_param lst

    var cursor = lst
    var tail : List_vt a?
    val () = loop {n} (pred, cursor, tail)
  in
    @(cursor, tail)
  end

(*------------------------------------------------------------------*)

implement {a}
list_vt_three_way_partition {n} (compare, pivot, lst) =
  //
  // WARNING: This implementation is NOT tail-recursive.
  //
  let
    var current_sign : int = 0

    val p_compare = [email protected] compare
    val p_pivot = [email protected] pivot
    val p_current_sign = [email protected] current_sign

    var pred =                  (* A linear closure. *)
      lam (elem : &a) : bool =<cloptr1>
        (* Return true iff the sign of the comparison of elem with the
           pivot matches the current_sign. *)
        let
          val @(pf_compare, fpf_compare | p_compare) =
            $UN.ptr0_vtake{(&a, &a) -<cloptr1> int} p_compare
          val @(pf_pivot, fpf_pivot | p_pivot) =
            $UN.ptr0_vtake{a} p_pivot
          val @(pf_current_sign, fpf_current_sign | p_current_sign) =
            $UN.ptr0_vtake{int} p_current_sign

          macdef compare = !p_compare
          macdef pivot = !p_pivot
          macdef current_sign = !p_current_sign

          val sign = compare (elem, pivot)
          val truth =
            (sign < 0 && current_sign < 0) ||
            (sign = 0 && current_sign = 0) ||
            (sign > 0 && current_sign > 0)

          prval () = fpf_compare pf_compare
          prval () = fpf_pivot pf_pivot
          prval () = fpf_current_sign pf_current_sign
        in
          truth
        end

    fun
    recurs {n            : nat}
           (compare      : &((&a, &a) -<cloptr1> int),
            pred         : &((&a) -<cloptr1> bool),
            pivot        : &a,
            current_sign : &int,
            lst          : list_vt (a, n))
          : [n1, n2, n3 : nat | n1 + n2 + n3 == n]
            @(list_vt (a, n1),
              list_vt (a, n2),
              list_vt (a, n3)) =
      case+ lst of
      | ~ NIL => @(NIL, NIL, NIL)
      | @ elem :: tail =>
        let
          macdef append = list_vt_append
          val cmp = compare (elem, pivot)
          val () = current_sign := cmp
          prval () = [email protected] lst
          val @(matches, rest) = list_vt_span (pred, lst)
          val @(left, middle, right) =
            recurs (compare, pred, pivot, current_sign, rest)
        in
          if cmp < 0 then
            @(matches \append left, middle, right)
          else if cmp = 0 then
            @(left, matches \append middle, right)
          else
            @(left, middle, matches \append right)
        end

    prval () = lemma_list_vt_param lst
    val retvals = recurs (compare, pred, pivot, current_sign, lst)

    val () = cloptr_free ($UN.castvwtp0{cloptr0} pred)
  in
    retvals
  end

(*------------------------------------------------------------------*)

fn {a : [email protected]}
three_way_partition_with_random_pivot
          {n       : nat}
          (compare : &((&a, &a) -<cloptr1> int),
           n       : int n,
           lst     : list_vt (a, n))
  : [n1, n2, n3 : nat | n1 + n2 + n3 == n]
    @(int n1, list_vt (a, n1),
      int n2, list_vt (a, n2),
      int n3, list_vt (a, n3)) =
let
  macdef append = list_vt_append

  var pivot : a

  val randnum = random_double ()
  val i_pivot = $UN.cast{Size_t} (randnum * $UN.cast{double} n)
  prval () = lemma_g1uint_param i_pivot
  val () = assertloc (i_pivot < i2sz n)
  val i_pivot = sz2i i_pivot

  val @(left, right) = list_vt_split_at (lst, i_pivot)
  val+ ~ (pivot_val :: right) = right
  val () = pivot := pivot_val

  val @(left1, middle1, right1) =
    list_vt_three_way_partition (compare, pivot, left)
  val @(left2, middle2, right2) =
    list_vt_three_way_partition (compare, pivot, right)

  val left = left1 \append left2
  val middle = middle1 \append (pivot :: middle2)
  val right = right1 \append right2

  val n1 = length left
  val n2 = length middle
  val n3 = n - n1 - n2
in
  @(n1, left, n2, middle, n3, right)
end

(*------------------------------------------------------------------*)

implement {a}
list_vt_three_way_separation {n, k} (compare, k, lst) =
  (* This is a quickselect with random pivot, returning a three-way
     partition, in which the middle partition contains the (k+1)st
     least element. *)
  let
    macdef append = list_vt_append

    fun
    loop {n1, n2, n3, k : nat | 0 <= k; k < n;
                                n1 + n2 + n3 == n}
         (compare : &((&a, &a) -<cloptr1> int),
          k       : int k,
          n1      : int n1,
          left    : list_vt (a, n1),
          n2      : int n2,
          middle  : list_vt (a, n2),
          n3      : int n3,
          right   : list_vt (a, n3))
        : [n1, n2, n3 : nat | n1 + n2 + n3 == n;
                              n1 <= k; k < n1 + n2]
          @(int n1, list_vt (a, n1),
            int n2, list_vt (a, n2),
            int n3, list_vt (a, n3)) =
      if k < n1 then
        let
          val @(m1, left1, m2, middle1, m3, right1) =
            three_way_partition_with_random_pivot
              (compare, n1, left)
        in
          loop (compare, k, m1, left1, m2, middle1,
                m3 + n2 + n3,
                right1 \append (middle \append right))
        end
      else if n1 + n2 <= k then
        let
          val @(m1, left2, m2, middle2, m3, right2) =
            three_way_partition_with_random_pivot
              (compare, n3, right)
        in
          loop (compare, k, n1 + n2 + m1,
                left \append (middle \append left2),
                m2, middle2, m3, right2)
        end
      else
        @(n1, left, n2, middle, n3, right)

    prval () = lemma_list_vt_param lst

    val @(n1, left, n2, middle, n3, right) =
      three_way_partition_with_random_pivot
        (compare, length lst, lst)
  in
    loop (compare, k, n1, left, n2, middle, n3, right)
  end

(*------------------------------------------------------------------*)

implement {a}
list_vt_select_linear {n, k} (compare, k, lst) =
  (* This is a quickselect with random pivot. It is like
     list_vt_three_way_separation, but throws away parts of the list that
     will not be needed later on. *)
  let
    implement
    list_vt_freelin$clear (x) =
      $effmask_all list_vt_select_linear$clear (x)

    macdef append = list_vt_append

    fun
    loop {n1, n2, n3, k : nat | 0 <= k; k < n1 + n2 + n3}
         (compare : &((&a, &a) -<cloptr1> int),
          k       : int k,
          n1      : int n1,
          left    : list_vt (a, n1),
          n2      : int n2,
          middle  : list_vt (a, n2),
          n3      : int n3,
          right   : list_vt (a, n3)) : a =
      if k < n1 then
        let
          val () = list_vt_freelin middle
          val () = list_vt_freelin right
          val @(m1, left1, m2, middle1, m3, right1) =
            three_way_partition_with_random_pivot
              (compare, n1, left)
        in
          loop (compare, k, m1, left1, m2, middle1, m3, right1)
        end
      else if n1 + n2 <= k then
        let
          val () = list_vt_freelin left
          val () = list_vt_freelin middle
          val @(m1, left1, m2, middle1, m3, right1) =
            three_way_partition_with_random_pivot
              (compare, n3, right)
        in
          loop (compare, k - n1 - n2,
                m1, left1, m2, middle1, m3, right1)
        end
      else
        let
          val () = list_vt_freelin left
          val () = list_vt_freelin right
          val @(middle1, middle2) =
            list_vt_split_at (middle, k - n1)
          val () = list_vt_freelin middle1
          val+ ~ (element :: middle2) = middle2
          val () = list_vt_freelin middle2
        in
          element
        end

    prval () = lemma_list_vt_param lst

    val @(n1, left, n2, middle, n3, right) =
      three_way_partition_with_random_pivot
        (compare, length lst, lst)
  in
    loop (compare, k, n1, left, n2, middle, n3, right)
  end

implement {a}
list_vt_select {n, k} (compare, k, lst) =
  let
    implement
    list_vt_select_linear$clear (x) = ()
  in
    list_vt_select_linear {n, k} (compare, k, lst)
  end

(*------------------------------------------------------------------*)

implement {a}
list_vt_stable_sort {n} (compare, lst) =
  (* This is a stable quicksort with random pivot. *)
  let
    macdef append = list_vt_append

    fun
    recurs {n          : int}
           {n1, n2, n3 : nat | n1 + n2 + n3 == n}
           (compare : &((&a, &a) -<cloptr1> int),
            n1      : int n1,
            left    : list_vt (a, n1),
            n2      : int n2,
            middle  : list_vt (a, n2),
            n3      : int n3,
            right   : list_vt (a, n3))
        : @(int n, list_vt (a, n)) =
      if 1 < n1 then
        let
          val @(m1, left1, m2, middle1, m3, right1) =
            three_way_partition_with_random_pivot
              (compare, n1, left)
          val @(_, left) =
            recurs {n1} (compare, m1, left1, m2, middle1, m3, right1)
        in
          if 1 < n3 then
            let
              val @(m1, left1, m2, middle1, m3, right1) =
                three_way_partition_with_random_pivot
                  (compare, n3, right)
              val @(_, right) =
                recurs {n3} (compare, m1, left1, m2, middle1,
                             m3, right1)
            in
              @(n1 + n2 + n3, left \append (middle \append right))
            end
          else
            @(n1 + n2 + n3, left \append (middle \append right))
        end
      else if 1 < n3 then
        let
           val @(m1, left1, m2, middle1, m3, right1) =
            three_way_partition_with_random_pivot
              (compare, n3, right)
          val @(_, right) =
            recurs {n3} (compare, m1, left1, m2, middle1, m3, right1)
        in
          @(n1 + n2 + n3, left \append (middle \append right))
        end
      else
        @(n1 + n2 + n3, left \append (middle \append right))

    prval () = lemma_list_vt_param lst

    val @(n1, left, n2, middle, n3, right) =
      three_way_partition_with_random_pivot
        (compare, length lst, lst)
  in
    recurs {n} (compare, n1, left, n2, middle, n3, right)
  end

(*------------------------------------------------------------------*)

fn
print_kth (direction : int,
           k         : int,
           lst       : !List_vt int) : void =
  let
    var compare =
      lam (x : &int, y : &int) : int =<cloptr1>
        if x < y then
          ~direction
        else if x = y then
          0
        else
          direction

    val lst = copy<int> lst
    val n = length<int> lst
    val k = g1ofg0 k
    val () = assertloc (1 <= k)
    val () = assertloc (k <= n)
    val element = list_vt_select<int> (compare, k - 1, lst)

    val () = cloptr_free ($UN.castvwtp0{cloptr0} compare)
  in
    print! (element)
  end

fn
demonstrate_quickselect () : void =
  let
    var example_for_select = $list_vt (9, 8, 7, 6, 5, 0, 1, 2, 3, 4)

    val () = print! ("With < as order predicate:  ")
    val () = print_kth (1, 1, example_for_select)
    val () = print! (" ")
    val () = print_kth (1, 2, example_for_select)
    val () = print! (" ")
    val () = print_kth (1, 3, example_for_select)
    val () = print! (" ")
    val () = print_kth (1, 4, example_for_select)
    val () = print! (" ")
    val () = print_kth (1, 5, example_for_select)
    val () = print! (" ")
    val () = print_kth (1, 6, example_for_select)
    val () = print! (" ")
    val () = print_kth (1, 7, example_for_select)
    val () = print! (" ")
    val () = print_kth (1, 8, example_for_select)
    val () = print! (" ")
    val () = print_kth (1, 9, example_for_select)
    val () = print! (" ")
    val () = print_kth (1, 10, example_for_select)
    val () = println! ()

    val () = print! ("With > as order predicate:  ")
    val () = print_kth (~1, 1, example_for_select)
    val () = print! (" ")
    val () = print_kth (~1, 2, example_for_select)
    val () = print! (" ")
    val () = print_kth (~1, 3, example_for_select)
    val () = print! (" ")
    val () = print_kth (~1, 4, example_for_select)
    val () = print! (" ")
    val () = print_kth (~1, 5, example_for_select)
    val () = print! (" ")
    val () = print_kth (~1, 6, example_for_select)
    val () = print! (" ")
    val () = print_kth (~1, 7, example_for_select)
    val () = print! (" ")
    val () = print_kth (~1, 8, example_for_select)
    val () = print! (" ")
    val () = print_kth (~1, 9, example_for_select)
    val () = print! (" ")
    val () = print_kth (~1, 10, example_for_select)
    val () = println! ()

    val () = list_vt_free<int> example_for_select
  in
  end

fn
demonstrate_quicksort () : void =
  let
    var example_for_sort =
      $list_vt ("elephant", "duck", "giraffe", "deer",
                "earwig", "dolphin", "wildebeest", "pronghorn",
                "woodlouse", "whip-poor-will")

    var compare =
      lam (x : &stringGt 0,
           y : &stringGt 0) : int =<cloptr1>
        if x[0] < y[0] then
          ~1
        else if x[0] = y[0] then
          0
        else
          1

    val () = println! ("stable sort by first character:")
    val @(_, sorted_lst) =
      list_vt_stable_sort<stringGt 0>
        (compare, copy<stringGt 0> example_for_sort)
    val () = println! ($UN.castvwtp1{List0 string} sorted_lst)
  in
    list_vt_free<string> sorted_lst;
    list_vt_free<string> example_for_sort;
    cloptr_free ($UN.castvwtp0{cloptr0} compare)
  end

implement
main0 (argc, argv) =
  let

    (* Currently there is no demonstration of
       list_vt_three_way_separation. *)

    val demo_name =
      begin
        if 2 <= argc then
          $UN.cast{string} argv[1]
        else
          begin
            println!
              ("Please choose \"quickselect\" or \"quicksort\".");
            exit (1)
          end
      end : string

  in

    if demo_name = "quickselect" then
      demonstrate_quickselect ()
    else if demo_name = "quicksort" then
      demonstrate_quicksort ()
    else
      begin
        println! ("Please choose \"quickselect\" or \"quicksort\".");
        exit (1)
      end

  end

(*------------------------------------------------------------------*)


MyList := [9, 8, 7, 6, 5, 0, 1, 2, 3, 4]
Loop, 10
	Out .= Select(MyList, 1, MyList.MaxIndex(), A_Index) (A_Index = MyList.MaxIndex() ? "" : ", ")
MsgBox, % Out
return

Partition(List, Left, Right, PivotIndex) {
	PivotValue := List[PivotIndex]
	, Swap(List, pivotIndex, Right)
	, StoreIndex := Left
	, i := Left - 1
	Loop, % Right - Left
		if (List[j := i + A_Index] <= PivotValue)
			Swap(List, StoreIndex, j)
			, StoreIndex++
	Swap(List, Right, StoreIndex)
	return StoreIndex
}

Select(List, Left, Right, n) {
	if (Left = Right)
		return List[Left]
	Loop {
		PivotIndex := (Left + Right) // 2
		, PivotIndex := Partition(List, Left, Right, PivotIndex)
		if (n = PivotIndex)
			return List[n]
		else if (n < PivotIndex)
			Right := PivotIndex - 1
		else
			Left := PivotIndex + 1
	}
}

Swap(List, i1, i2) {
	t := List[i1]
	, List[i1] := List[i2]
	, List[i2] := t
}


#include <stdio.h>
#include <string.h>

int qselect(int *v, int len, int k)
{
#	define SWAP(a, b) { tmp = v[a]; v[a] = v[b]; v[b] = tmp; }
	int i, st, tmp;

	for (st = i = 0; i < len - 1; i++) {
		if (v[i] > v[len-1]) continue;
		SWAP(i, st);
		st++;
	}

	SWAP(len-1, st);

	return k == st	?v[st]
			:st > k	? qselect(v, st, k)
				: qselect(v + st, len - st, k - st);
}

int main(void)
{
#	define N (sizeof(x)/sizeof(x[0]))
	int x[] = {9, 8, 7, 6, 5, 0, 1, 2, 3, 4};
	int y[N];

	int i;
	for (i = 0; i < 10; i++) {
		memcpy(y, x, sizeof(x)); // qselect modifies array
		printf("%d: %d\n", i, qselect(y, 10, i));
	}

	return 0;
}


// ----------------------------------------------------------------------------------------------
//
//  Program.cs - QuickSelect
//
// ----------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;

namespace QuickSelect
{
    internal static class Program
    {
        #region Static Members

        private static void Main()
        {
            var inputArray = new[] {9, 8, 7, 6, 5, 0, 1, 2, 3, 4};
            // Loop 10 times
            Console.WriteLine( "Loop quick select 10 times." );
            for( var i = 0 ; i < 10 ; i++ )
            {
                Console.Write( inputArray.NthSmallestElement( i ) );
                if( i < 9 )
                    Console.Write( ", " );
            }
            Console.WriteLine();

            // And here is then more effective way to get N smallest elements from vector in order by using quick select algorithm
            // Basically we are here just sorting array (taking 10 smallest from array which length is 10)
            Console.WriteLine( "Just sort 10 elements." );
            Console.WriteLine( string.Join( ", ", inputArray.TakeSmallest( 10 ).OrderBy( v => v ).Select( v => v.ToString() ).ToArray() ) );
            // Here we are actually doing quick select once by taking only 4 smallest from array.
            Console.WriteLine( "Get 4 smallest and sort them." );
            Console.WriteLine( string.Join( ", ", inputArray.TakeSmallest( 4 ).OrderBy( v => v ).Select( v => v.ToString() ).ToArray() ) );
            Console.WriteLine( "< Press any key >" );
            Console.ReadKey();
        }

        #endregion
    }

    internal static class ArrayExtension
    {
        #region Static Members

        /// <summary>
        ///  Return specified number of smallest elements from array.
        /// </summary>
        /// <typeparam name="T">The type of the elements of array. Type must implement IComparable(T) interface.</typeparam>
        /// <param name="array">The array to return elemnts from.</param>
        /// <param name="count">The number of smallest elements to return. </param>
        /// <returns>An IEnumerable(T) that contains the specified number of smallest elements of the input array. Returned elements are NOT sorted.</returns>
        public static IEnumerable<T> TakeSmallest<T>( this T[] array, int count ) where T : IComparable<T>
        {
            if( count < 0 )
                throw new ArgumentOutOfRangeException( "count", "Count is smaller than 0." );
            if( count == 0 )
                return new T[0];
            if( array.Length <= count )
                return array;

            return QuickSelectSmallest( array, count - 1 ).Take( count );
        }

        /// <summary>
        /// Returns N:th smallest element from the array.
        /// </summary>
        /// <typeparam name="T">The type of the elements of array. Type must implement IComparable(T) interface.</typeparam>
        /// <param name="array">The array to return elemnt from.</param>
        /// <param name="n">Nth element. 0 is smallest element, when array.Length - 1 is largest element.</param>
        /// <returns>N:th smalles element from the array.</returns>
        public static T NthSmallestElement<T>( this T[] array, int n ) where T : IComparable<T>
        {
            if( n < 0 || n > array.Length - 1 )
                throw new ArgumentOutOfRangeException( "n", n, string.Format( "n should be between 0 and {0} it was {1}.", array.Length - 1, n ) );
            if( array.Length == 0 )
                throw new ArgumentException( "Array is empty.", "array" );
            if( array.Length == 1 )
                return array[ 0 ];

            return QuickSelectSmallest( array, n )[ n ];
        }

        /// <summary>
        ///  Partially sort array such way that elements before index position n are smaller or equal than elemnt at position n. And elements after n are larger or equal.
        /// </summary>
        /// <typeparam name="T">The type of the elements of array. Type must implement IComparable(T) interface.</typeparam>
        /// <param name="input">The array which elements are being partially sorted. This array is not modified.</param>
        /// <param name="n">Nth smallest element.</param>
        /// <returns>Partially sorted array.</returns>
        private static T[] QuickSelectSmallest<T>( T[] input, int n ) where T : IComparable<T>
        {
            // Let's not mess up with our input array
            // For very large arrays - we should optimize this somehow - or just mess up with our input
            var partiallySortedArray = (T[]) input.Clone();

            // Initially we are going to execute quick select to entire array
            var startIndex = 0;
            var endIndex = input.Length - 1;

            // Selecting initial pivot
            // Maybe we are lucky and array is sorted initially?
            var pivotIndex = n;

            // Loop until there is nothing to loop (this actually shouldn't happen - we should find our value before we run out of values)
            var r = new Random();
            while( endIndex > startIndex )
            {
                pivotIndex = QuickSelectPartition( partiallySortedArray, startIndex, endIndex, pivotIndex );
                if( pivotIndex == n )
                    // We found our n:th smallest value - it is stored to pivot index
                    break;
                if( pivotIndex > n )
                    // Array before our pivot index have more elements that we are looking for
                    endIndex = pivotIndex - 1;
                else
                    // Array before our pivot index has less elements that we are looking for
                    startIndex = pivotIndex + 1;

                // Omnipotent beings don't need to roll dices - but we do...
                // Randomly select a new pivot index between end and start indexes (there are other methods, this is just most brutal and simplest)
                pivotIndex = r.Next( startIndex,  endIndex );
            }
            return partiallySortedArray;
        }

        /// <summary>
        /// Sort elements in sub array between startIndex and endIndex, such way that elements smaller than or equal with value initially stored to pivot index are before
        /// new returned pivot value index.
        /// </summary>
        /// <typeparam name="T">The type of the elements of array. Type must implement IComparable(T) interface.</typeparam>
        /// <param name="array">The array that is being sorted.</param>
        /// <param name="startIndex">Start index of sub array.</param>
        /// <param name="endIndex">End index of sub array.</param>
        /// <param name="pivotIndex">Pivot index.</param>
        /// <returns>New pivot index. Value that was initially stored to <paramref name="pivotIndex"/> is stored to this newly returned index. All elements before this index are
        /// either smaller or equal with pivot value. All elements after this index are larger than pivot value.</returns>
        /// <remarks>This method modifies paremater array.</remarks>
        private static int QuickSelectPartition<T>( this T[] array, int startIndex, int endIndex, int pivotIndex ) where T : IComparable<T>
        {
            var pivotValue = array[ pivotIndex ];
            // Initially we just assume that value in pivot index is largest - so we move it to end (makes also for loop more straight forward)
            array.Swap( pivotIndex, endIndex );
            for( var i = startIndex ; i < endIndex ; i++ )
            {
                if( array[ i ].CompareTo( pivotValue ) > 0 )
                    continue;

                // Value stored to i was smaller than or equal with pivot value - let's move it to start
                array.Swap( i, startIndex );
                // Move start one index forward
                startIndex++;
            }
            // Start index is now pointing to index where we should store our pivot value from end of array
            array.Swap( endIndex, startIndex );
            return startIndex;
        }

        private static void Swap<T>( this T[] array, int index1, int index2 )
        {
            if( index1 == index2 )
                return;

            var temp = array[ index1 ];
            array[ index1 ] = array[ index2 ];
            array[ index2 ] = temp;
        }

        #endregion
    }
}


#include <algorithm>
#include <iostream>

int main() {
  for (int i = 0; i < 10; i++) {
    int a[] = {9, 8, 7, 6, 5, 0, 1, 2, 3, 4};
    std::nth_element(a, a + i, a + sizeof(a)/sizeof(*a));
    std::cout << a[i];
    if (i < 9) std::cout << ", ";
  }
  std::cout << std::endl;

  return 0;
}


quick = cluster [T: type] is select
        where T has lt: proctype (T,T) returns (bool)
    aT = array[T]
    sT = sequence[T]
    rep = null

    swap = proc (list: aT, a, b: int)
        temp: T := list[a]
        list[a] := list[b]
        list[b] := temp
    end swap

    partition = proc (list: aT, left, right, pivotIndex: int) returns (int)
        pivotValue: T := list[pivotIndex]
        swap(list, pivotIndex, right)
        storeIndex: int := left
        for i: int in int$from_to(left, right-1) do
            if list[i] < pivotValue then
                swap(list, storeIndex, i)
                storeIndex := storeIndex + 1
            end
        end
        swap(list, right, storeIndex)
        return(storeIndex)
    end partition

    _select = proc (list: aT, left, right, k: int) returns (T)
        if left = right then
            return(list[left])
        end

        pivotIndex: int := left + (right - left + 1) / 2
        pivotIndex := partition(list, left, right, pivotIndex)
        if k = pivotIndex then
            return(list[k])
        elseif k < pivotIndex then
            return(_select(list, left, pivotIndex-1, k))
        else
            return(_select(list, pivotIndex + 1, right, k))
        end
    end _select

    select = proc (list: sT, k: int) returns (T)
        return(_select(sT$s2a(list), 1, sT$size(list), k))
    end select
end quick

start_up = proc ()
    po: stream := stream$primary_output()
    vec: sequence[int] := sequence[int]$[9,8,7,6,5,0,1,2,3,4]

    for k: int in int$from_to(1, 10) do
        item: int := quick[int]$select(vec, k)
        stream$putl(po, int$unparse(k) || ": " || int$unparse(item))
    end
end start_up


       CLASS-ID MainProgram.

       METHOD-ID Partition STATIC USING T.
       CONSTRAINTS.
           CONSTRAIN T IMPLEMENTS type IComparable.

       DATA DIVISION.
       LOCAL-STORAGE SECTION.
       01  pivot-val              T.

       PROCEDURE DIVISION USING VALUE arr AS T OCCURS ANY,
               left-idx AS BINARY-LONG, right-idx AS BINARY-LONG,
               pivot-idx AS BINARY-LONG
               RETURNING ret AS BINARY-LONG.
           MOVE arr (pivot-idx) TO pivot-val
           INVOKE self::Swap(arr, pivot-idx, right-idx)
           DECLARE store-idx AS BINARY-LONG = left-idx
           PERFORM VARYING i AS BINARY-LONG FROM left-idx BY 1
                   UNTIL i > right-idx
               IF arr (i) < pivot-val
                   INVOKE self::Swap(arr, i, store-idx)
                   ADD 1 TO store-idx
               END-IF
           END-PERFORM
           INVOKE self::Swap(arr, right-idx, store-idx)

           MOVE store-idx TO ret
       END METHOD.

       METHOD-ID Quickselect STATIC USING T.
       CONSTRAINTS.
           CONSTRAIN T IMPLEMENTS type IComparable.

       PROCEDURE DIVISION USING VALUE arr AS T OCCURS ANY,
               left-idx AS BINARY-LONG, right-idx AS BINARY-LONG,
               n AS BINARY-LONG
               RETURNING ret AS T.
           IF left-idx = right-idx
               MOVE arr (left-idx) TO ret
               GOBACK
           END-IF

           DECLARE rand AS TYPE Random = NEW Random()
           DECLARE pivot-idx AS BINARY-LONG = rand::Next(left-idx, right-idx)
           DECLARE pivot-new-idx AS BINARY-LONG
               = self::Partition(arr, left-idx, right-idx, pivot-idx)
           DECLARE pivot-dist AS BINARY-LONG = pivot-new-idx - left-idx + 1

           EVALUATE TRUE
               WHEN pivot-dist = n
                   MOVE arr (pivot-new-idx) TO ret

               WHEN n < pivot-dist
                   INVOKE self::Quickselect(arr, left-idx, pivot-new-idx - 1, n)
                       RETURNING ret

               WHEN OTHER
                   INVOKE self::Quickselect(arr, pivot-new-idx + 1, right-idx,
                       n - pivot-dist) RETURNING ret
           END-EVALUATE
       END METHOD.

       METHOD-ID Swap STATIC USING T.
       CONSTRAINTS.
           CONSTRAIN T IMPLEMENTS type IComparable.

       DATA DIVISION.
       LOCAL-STORAGE SECTION.
       01  temp                   T.

       PROCEDURE DIVISION USING arr AS T OCCURS ANY,
               VALUE idx-1 AS BINARY-LONG, idx-2 AS BINARY-LONG.
           IF idx-1 <> idx-2
               MOVE arr (idx-1) TO temp
               MOVE arr (idx-2) TO arr (idx-1)
               MOVE temp TO arr (idx-2)
           END-IF
       END METHOD.

       METHOD-ID Main STATIC.
       PROCEDURE DIVISION.
           DECLARE input-array AS BINARY-LONG OCCURS ANY
               = TABLE OF BINARY-LONG(9, 8, 7, 6, 5, 0, 1, 2, 3, 4)
           DISPLAY "Loop quick select 10 times."
           PERFORM VARYING i AS BINARY-LONG FROM 1 BY 1 UNTIL i > 10
               DISPLAY self::Quickselect(input-array, 1, input-array::Length, i)
                   NO ADVANCING

               IF i < 10
                   DISPLAY ", " NO ADVANCING
               END-IF
           END-PERFORM
           DISPLAY SPACE
       END METHOD.
       END CLASS.


(defun quickselect (n _list)
  (let* ((ys (remove-if (lambda (x) (< (car _list) x)) (cdr _list)))
         (zs (remove-if-not (lambda (x) (< (car _list) x)) (cdr _list)))
         (l (length ys))
         )
    (cond ((< n l) (quickselect n ys))
          ((> n l) (quickselect (- n l 1) zs))
          (t (car _list)))
    )
  )

(defparameter a '(9 8 7 6 5 0 1 2 3 4))
(format t "~a~&" (mapcar (lambda (x) (quickselect x a)) (loop for i from 0 below (length a) collect i)))


def quickselect(a, k)
  arr = a.dup # we will be modifying it
  loop do
    pivot = arr.delete_at(rand(arr.size))
    left, right = arr.partition { |x| x < pivot }
    if k == left.size
      return pivot
    elsif k < left.size
      arr = left
    else
      k = k - left.size - 1
      arr = right
    end
  end
end

v = [9, 8, 7, 6, 5, 0, 1, 2, 3, 4]
p v.each_index.map { |i| quickselect(v, i) }.to_a


void main() {
    import std.stdio, std.algorithm;

    auto a = [9, 8, 7, 6, 5, 0, 1, 2, 3, 4];
    foreach (immutable i; 0 .. a.length) {
        a.topN(i);
        write(a[i], " ");
    }
}


program Quickselect_algorithm;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

function quickselect(list: TArray<Integer>; k: Integer): Integer;

  procedure Swap(i, j: Integer);
  var
    tmp: Integer;
  begin
    tmp := list[i];
    list[i] := list[j];
    list[j] := tmp;
  end;

begin
  repeat
    var px := length(list) div 2;
    var pv := list[px];
    var last := length(list) - 1;

    Swap(px, last);
    var i := 0;
    for var j := 0 to last - 1 do
      if list[j] < pv then
      begin
        swap(i, j);
        inc(i);
      end;

    if i = k then
      exit(pv);

    if k < i then
      delete(list, i, length(list))
    else
    begin
      Swap(i, last);
      delete(list, 0, i + 1);
      dec(k, i + 1);
    end;
  until false;
end;

begin
  var i := 0;

  while True do
  begin
    var v: TArray<Integer> := [9, 8, 7, 6, 5, 0, 1, 2, 3, 4];
    if i = length(v) then
      Break;
    Writeln(quickselect(v, i));
    inc(i);
  end;
  Readln;
end.


func qselect k d[] . res .
  #
  subr partition
    mid = left
    for i = left + 1 to right
      if d[i] < d[left]
        mid += 1
        swap d[i] d[mid]
      .
    .
    swap d[left] d[mid]
  .
  right = len d[] - 1
  repeat
    call partition
    until mid = k
    if mid < k
      left = mid + 1
    else
      right = mid - 1
    .
  .
  res = d[k]
.
d[] = [ 9 8 7 6 5 0 1 2 3 4 ]
for i range len d[]
  call qselect i d[] r
  print r
.


defmodule Quick do
  def select(k, [x|xs]) do
    {ys, zs} = Enum.partition(xs, fn e -> e < x end)
    l = length(ys)
    cond do
      k < l -> select(k, ys)
      k > l -> select(k - l - 1, zs)
      true  -> x
    end
  end

  def test do
    v = [9, 8, 7, 6, 5, 0, 1, 2, 3, 4]
    Enum.map(0..length(v)-1, fn i -> select(i,v) end)
    |> IO.inspect
  end
end

Quick.test


-module(quickselect).

-export([test/0]).

test() ->
    V = [9, 8, 7, 6, 5, 0, 1, 2, 3, 4],
    lists:map(
        fun(I) -> quickselect(I,V) end,
        lists:seq(0, length(V) - 1)
    ).

quickselect(K, [X | Xs]) ->
    {Ys, Zs} =
        lists:partition(fun(E) -> E < X end, Xs),
    L = length(Ys),
    if
        K < L ->
            quickselect(K, Ys);
        K > L ->
            quickselect(K - L - 1, Zs);
        true ->
            X
    end.


let rec quickselect k list =
    match list with
    | [] -> failwith "Cannot take largest element of empty list."
    | [a] -> a
    | x::xs ->
        let (ys, zs) = List.partition (fun arg -> arg < x) xs
        let l = List.length ys
        if k < l then quickselect k ys
        elif k > l then quickselect (k-l-1) zs
        else x
//end quickselect

[<EntryPoint>]
let main args =
    let v = [9; 8; 7; 6; 5; 0; 1; 2; 3; 4]
    printfn "%A" [for i in 0..(List.length v - 1) -> quickselect i v]
    0


USING: combinators kernel make math locals prettyprint sequences ;
IN: rosetta-code.quickselect

:: quickselect ( k seq -- n )
    seq unclip :> ( xs x )
    xs [ x < ] partition :> ( ys zs )
    ys length :> l
    {
        { [ k l < ] [ k ys quickselect ] }
        { [ k l > ] [ k l - 1 - zs quickselect ] }
        [ x ]
    } cond ;

: quickselect-demo ( -- )
    { 9 8 7 6 5 0 1 2 3 4 } dup length <iota> swap
    [ [ quickselect , ] curry each ] { } make . ;

MAIN: quickselect-demo


      INTEGER FUNCTION FINDELEMENT(K,A,N)	!I know I can.
Chase an order statistic: FindElement(N/2,A,N) leads to the median, with some odd/even caution.
Careful! The array is shuffled: for i < K, A(i) <= A(K); for i > K, A(i) >= A(K).
Charles Anthony Richard Hoare devised this method, as related to his famous QuickSort.
       INTEGER K,N		!Find the K'th element in order of an array of N elements, not necessarily in order.
       INTEGER A(N),HOPE,PESTY	!The array, and like associates.
       INTEGER L,R,L2,R2	!Fingers.
        L = 1			!Here we go.
        R = N			!The bounds of the work area within which the K'th element lurks.
        DO WHILE (L .LT. R)	!So, keep going until it is clamped.
          HOPE = A(K)		!If array A is sorted, this will be rewarded.
          L2 = L		!But it probably isn't sorted.
          R2 = R		!So prepare a scan.
          DO WHILE (L2 .LE. R2)	!Keep squeezing until the inner teeth meet.
            DO WHILE (A(L2) .LT. HOPE)	!Pass elements less than HOPE.
              L2 = L2 + 1		!Note that at least element A(K) equals HOPE.
            END DO			!Raising the lower jaw.
            DO WHILE (HOPE .LT. A(R2))	!Elements higher than HOPE
              R2 = R2 - 1		!Are in the desired place.
            END DO			!And so we speed past them.
            IF (L2 - R2) 1,2,3	!How have the teeth paused?
    1       PESTY = A(L2)		!On grit. A(L2) > HOPE and A(R2) < HOPE.
            A(L2) = A(R2)		!So swap the two troublemakers.
            A(R2) = PESTY		!To be as if they had been in the desired order all along.
    2       L2 = L2 + 1		!Advance my teeth.
            R2 = R2 - 1		!As if they hadn't paused on this pest.
    3     END DO		!And resume the squeeze, hopefully closing in K.
          IF (R2 .LT. K) L = L2	!The end point gives the order position of value HOPE.
          IF (K .LT. L2) R = R2	!But we want the value of order position K.
        END DO			!Have my teeth met yet?
        FINDELEMENT = A(K)	!Yes. A(K) now has the K'th element in order.
      END FUNCTION FINDELEMENT	!Remember! Array A has likely had some elements moved!

      PROGRAM POKE
      INTEGER FINDELEMENT	!Not the default type for F.
      INTEGER N			!The number of elements.
      PARAMETER (N = 10)	!Fixed for the test problem.
      INTEGER A(66)		!An array of integers.
      DATA A(1:N)/9, 8, 7, 6, 5, 0, 1, 2, 3, 4/	!The specified values.

      WRITE (6,1) A(1:N)	!Announce, and add a heading.
    1 FORMAT ("Selection of the i'th element in order from an array.",/
     1 "The array need not be in order, and may be reordered.",/
     2 "  i Val:Array elements...",/,8X,666I2)

      DO I = 1,N	!One by one,
        WRITE (6,2) I,FINDELEMENT(I,A,N),A(1:N)	!Request the i'th element.
    2   FORMAT (I3,I4,":",666I2)	!Match FORMAT 1.
      END DO		!On to the next trial.

      END	!That was easy.


Dim Shared As Long array(9), pivote

Function QuickPartition (array() As Long, izda As Long, dcha As Long, pivote As Long) As Long
    Dim As Long pivotValue = array(pivote)
    Swap array(pivote), array(dcha)
    Dim As Long indice = izda
    For i As Long = izda To dcha-1
        If array(i) < pivotValue Then
            Swap array(indice), array(i)
            indice += 1
        End If
    Next i
    Swap array(dcha), array(indice)
    Return indice
End Function

Function QuickSelect(array() As Long, izda As Long, dcha As Long, k As Long) As Long
    Do
        If izda = dcha Then Return array(izda) : End If
        pivote = izda
        pivote = QuickPartition(array(), izda, dcha, pivote)
        Select Case k
        Case pivote
            Return array(k)
        Case Is < pivote
            dcha = pivote - 1
        Case Is > pivote
            izda = pivote + 1
        End Select
    Loop
End Function

Dim As Long a = Lbound(array), b = Ubound(array)
Print "Array desordenado:  ";
For i As Long = a To b
    Read array(i)
    Print array(i);
Next i
Data 9, 8, 7, 6, 5, 0, 1, 2, 3, 4

Print !"\n\n   Array ordenado:  ";
For i As Long = a To b
    Print QuickSelect(array(), a, b, i);
Next i
Sleep


package main

import "fmt"

func quickselect(list []int, k int) int {
    for {
        // partition
        px := len(list) / 2
        pv := list[px]
        last := len(list) - 1
        list[px], list[last] = list[last], list[px]
        i := 0
        for j := 0; j < last; j++ {
            if list[j] < pv {
                list[i], list[j] = list[j], list[i]
                i++
            }
        }
        // select
        if i == k {
            return pv
        }
        if k < i {
            list = list[:i]
        } else {
            list[i], list[last] = list[last], list[i]
            list = list[i+1:]
            k -= i + 1
        }
    }
}

func main() {
    for i := 0; ; i++ {
        v := []int{9, 8, 7, 6, 5, 0, 1, 2, 3, 4}
        if i == len(v) {
            return
        }
        fmt.Println(quickselect(v, i))
    }
}


import Data.List (partition)

quickselect
  :: Ord a
  => [a] -> Int -> a
quickselect (x:xs) k
  | k < l = quickselect ys k
  | k > l = quickselect zs (k - l - 1)
  | otherwise = x
  where
    (ys, zs) = partition (< x) xs
    l = length ys

main :: IO ()
main =
  print
    ((fmap . quickselect) <*> zipWith const [0 ..] $
     [9, 8, 7, 6, 5, 0, 1, 2, 3, 4])


procedure main(A)
    every writes(" ",select(1 to *A, A, 1, *A)|"\n")
end

procedure select(k,A,min,max)
    repeat {
        pNI := partition(?(max-min)+min, A, min, max)
        pD := pNI - min + 1
        if pD = k then return A[pNI]
        if k < pD then max := pNI-1
        else (k -:= pD, min := pNI+1)
        }
end

procedure partition(pivot,A,min,max)
    pV := (A[max] :=: A[pivot])
    sI := min
    every A[i := min to max-1] <= pV do (A[sI] :=: A[i], sI +:= 1)
    A[max] :=: A[sI]
    return sI
end


quickselect=:4 :0
  if. 0=#y do. _ return. end.
  n=.?#y
  m=.n{y
  if. x < m do.
    x quickselect (m>y)#y
  else.
    if. x > m do.
      x quickselect (m<y)#y
    else.
      m
    end.
  end.
)


import java.util.Random;

public class QuickSelect {

	private static <E extends Comparable<? super E>> int partition(E[] arr, int left, int right, int pivot) {
		E pivotVal = arr[pivot];
		swap(arr, pivot, right);
		int storeIndex = left;
		for (int i = left; i < right; i++) {
			if (arr[i].compareTo(pivotVal) < 0) {
				swap(arr, i, storeIndex);
				storeIndex++;
			}
		}
		swap(arr, right, storeIndex);
		return storeIndex;
	}

	private static <E extends Comparable<? super E>> E select(E[] arr, int n) {
		int left = 0;
		int right = arr.length - 1;
		Random rand = new Random();
		while (right >= left) {
			int pivotIndex = partition(arr, left, right, rand.nextInt(right - left + 1) + left);
			if (pivotIndex == n) {
				return arr[pivotIndex];
			} else if (pivotIndex < n) {
				left = pivotIndex + 1;
			} else {
				right = pivotIndex - 1;
			}
		}
		return null;
	}

	private static void swap(Object[] arr, int i1, int i2) {
		if (i1 != i2) {
			Object temp = arr[i1];
			arr[i1] = arr[i2];
			arr[i2] = temp;
		}
	}

	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			Integer[] input = {9, 8, 7, 6, 5, 0, 1, 2, 3, 4};
			System.out.print(select(input, i));
			if (i < 9) System.out.print(", ");
		}
		System.out.println();
	}

}


// this just helps make partition read better
function swap(items, firstIndex, secondIndex) {
  var temp = items[firstIndex];
  items[firstIndex] = items[secondIndex];
  items[secondIndex] = temp;
};

// many algorithms on this page violate
// the constraint that partition operates in place
function partition(array, from, to) {
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
  var pivotIndex = getRandomInt(from, to),
      pivot = array[pivotIndex];
  swap(array, pivotIndex, to);
  pivotIndex = from;

  for(var i = from; i <= to; i++) {
    if(array[i] < pivot) {
      swap(array, pivotIndex, i);
      pivotIndex++;
    }
  };
  swap(array, pivotIndex, to);

  return pivotIndex;
};

// later versions of JS have TCO so this is safe
function quickselectRecursive(array, from, to, statistic) {
  if(array.length === 0 || statistic > array.length - 1) {
    return undefined;
  };

  var pivotIndex = partition(array, from, to);
  if(pivotIndex === statistic) {
    return array[pivotIndex];
  } else if(pivotIndex < statistic) {
    return quickselectRecursive(array, pivotIndex, to, statistic);
  } else if(pivotIndex > statistic) {
    return quickselectRecursive(array, from, pivotIndex, statistic);
  }
};

function quickselectIterative(array, k) {
  if(array.length === 0 || k > array.length - 1) {
    return undefined;
  };

  var from = 0, to = array.length,
      pivotIndex = partition(array, from, to);

  while(pivotIndex !== k) {
    pivotIndex = partition(array, from, to);
    if(pivotIndex < k) {
      from = pivotIndex;
    } else if(pivotIndex > k) {
      to = pivotIndex;
    }
  };

  return array[pivotIndex];
};

KthElement = {
  find: function(array, element) {
    var k = element - 1;
    return quickselectRecursive(array, 0, array.length, k);
    // you can also try out the Iterative version
    // return quickselectIterative(array, k);
  }
}


# Emit the k-th smallest item in the input array,
# or nothing if k is too small or too large.
# The smallest corresponds to k==1.
# The input array may hold arbitrary JSON entities, including null.
def quickselect(k):

  def partition(pivot):
    reduce .[] as $x
      # state: [less, other]
      ( [ [], [] ];                       # two empty arrays:
        if    $x  < pivot
        then .[0] += [$x]                 # add x to less
        else .[1] += [$x]                 # add x to other
        end
      );

  # recursive inner function has arity 0 for efficiency
  def qs:  # state: [kn, array] where kn counts from 0
    .[0] as $kn
     | .[1] as $a
    | $a[0] as $pivot
    | ($a[1:] | partition($pivot)) as $p
    | $p[0] as $left
    | ($left|length) as $ll
    | if   $kn == $ll then $pivot
      elif $kn <  $ll then [$kn, $left] | qs
      else [$kn - $ll - 1, $p[1] ] | qs
      end;

  if length < k or k <= 0 then empty else [k-1, .] | qs end;


// version 1.1.2

const val MAX = Int.MAX_VALUE
val rand = java.util.Random()

fun partition(list:IntArray, left: Int, right:Int, pivotIndex: Int): Int {
    val pivotValue = list[pivotIndex]
    list[pivotIndex] = list[right]
    list[right] = pivotValue
    var storeIndex = left
    for (i in left until right) {
        if (list[i] < pivotValue) {
            val tmp = list[storeIndex]
            list[storeIndex] = list[i]
            list[i] = tmp
            storeIndex++
        }
    }
    val temp = list[right]
    list[right] = list[storeIndex]
    list[storeIndex] = temp
    return storeIndex
}

tailrec fun quickSelect(list: IntArray, left: Int, right: Int, k: Int): Int {
    if (left == right) return list[left]
    var pivotIndex = left + Math.floor((rand.nextInt(MAX) % (right - left + 1)).toDouble()).toInt()
    pivotIndex = partition(list, left, right, pivotIndex)
    if (k == pivotIndex)
        return list[k]
    else if (k < pivotIndex)
        return quickSelect(list, left, pivotIndex - 1, k)
    else
        return quickSelect(list, pivotIndex + 1, right, k)
}

fun main(args: Array<String>) {
    val list = intArrayOf(9, 8, 7, 6, 5, 0, 1, 2, 3, 4)
    val right = list.size - 1
    for (k in 0..9) {
        print(quickSelect(list, 0, right, k))
        if (k < 9) print(", ")
    }
    println()
}


function partition (list, left, right, pivotIndex)
    local pivotValue = list[pivotIndex]
    list[pivotIndex], list[right] = list[right], list[pivotIndex]
    local storeIndex = left
    for i = left, right do
        if list[i] < pivotValue then
            list[storeIndex], list[i] = list[i], list[storeIndex]
            storeIndex = storeIndex + 1
        end
    end
    list[right], list[storeIndex] = list[storeIndex], list[right]
    return storeIndex
end

function quickSelect (list, left, right, n)
    local pivotIndex
    while 1 do
        if left == right then return list[left] end
        pivotIndex = math.random(left, right)
        pivotIndex = partition(list, left, right, pivotIndex)
        if n == pivotIndex then
            return list[n]
        elseif n < pivotIndex then
            right = pivotIndex - 1
        else
            left = pivotIndex + 1
        end
    end
end

math.randomseed(os.time())
local vec = {9, 8, 7, 6, 5, 0, 1, 2, 3, 4}
for i = 1, 10 do print(i, quickSelect(vec, 1, #vec, i) .. " ") end


part := proc(arr, left, right, pivot)
	local val,safe,i:
	val := arr[pivot]:
	arr[pivot], arr[right] := arr[right], arr[pivot]:
	safe := left:
	for i from left to right do
		if arr[i] < val then
			arr[safe], arr[i] := arr[i], arr[safe]:
			safe := safe + 1:
		end if:
	end do:
	arr[right], arr[safe] := arr[safe], arr[right]:
	return safe:
end proc:

quickselect := proc(arr,k)
	local pivot,left,right:
	left,right := 1,numelems(arr):
	while(true)do
		if left = right then return arr[left]: end if:
		pivot := trunc((left+right)/2);
		pivot := part(arr, left, right, pivot):
		if k = pivot then
			return arr[k]:
		elif k < pivot then
			right := pivot-1:
		else
			left := pivot+1:
		end if:
	end do:
end proc:
roll := rand(1..20):
demo := Array([seq(roll(), i=1..20)]);
map(x->printf("%d ", x), demo):
print(quickselect(demo,7)):
print(quickselect(demo,14)):


Quickselect[ds : DataStructure["DynamicArray", _], k_] := QuickselectWorker[ds, 1, ds["Length"], k];
QuickselectWorker[ds_, low0_, high0_, k_] := Module[{pivotIdx, low = low0, high = high0},
   While[True,
    If[low === high,
     Return[ds["Part", low]]
     ];
    pivotIdx = SelectPartition[ds, low, high];
    Which[k === pivotIdx,
     Return[ds["Part", k]],
     k < pivotIdx,
     high = pivotIdx - 1,
     True,
     low = pivotIdx + 1
     ]
    ]
   ];
SelectPartition[ds_, low_, high_] := Module[{pivot = ds["Part", high], i = low, j},
   Do[
    If[ds["Part", j] <= pivot,
     ds["SwapPart", i, j];
     i = i + 1
     ]
    ,
    {j, low, high - 1}
    ];
   ds["SwapPart", i, high];
   i
   ];
ds = CreateDataStructure["DynamicArray", {9, 8, 7, 6, 5, 0, 1, 2, 3, 4}];
Quickselect[ds, #] & /@ Range[10]