Perl Weekly Challenge 139: JortSort

by Abigail

Challenge

You are given a list of numbers.

Write a script to implement JortSort. It should return true/false depending if the given list of numbers are already sorted.

Example 1

Input: @n = (1,2,3,4,5)
Output: 1

Since the array is sorted, it prints 1.

Example 2

Input: @n = (1,3,2,4,5)
Output: 0

Since the array is NOT sorted, it prints 0.

Discussion

JortSort is a joke.

The original jortSort actually sorts input, then compares the sorted input with the original input.

It's not clear whether sorting is necessary for a jortSort, or whether any function which returns whether its input is sorted or not qualifies as a jortSort. The challenge is silent on this subject. So, we won't bother with sorting, and just check whether the input is sorted or not.

Solution

A list \(L\) is sorted, if and only if, there isn't an index \(i > 0\) such that \(L [i - i] > L [i]\).

And that translates to a very simple piece of code.

AWK

{
    sorted = 1
    for (i = 2; i <= NF; i ++) {
        if ($(i - 1) > $i) {
            sorted = 0
        }
    }
    print sorted
}

AWK already splits the input for us, putting the values into $1, $2, etc.

Find the full program on GitHub.

Bash

After reading the input into an array list, we'll do:

((sorted = 1))
for ((i = 1; i < ${#list[@]}; i ++))
do  if ((${list[$i - 1]} > ${list[$i]}))
    then ((sorted = 0))
    fi
done
echo $sorted

Find the full program on GitHub.

bc

In our bc solution, we assume the input is terminated by a 0.

prev = read()
sorted = 1;
while (1) {
    next = read()
    if (next == 0) { # End of input
        sorted
        break 
    }
    if (prev > next) {
        sorted = 0
    }
    prev = next
}

Find the full program on GitHub.

C

Here, we pick up the code after we have read a line of input into the variable line, of type char *.

int offset = 0;
int off;
int prev, next;   
bool sorted = true;
if (sscanf (line, "%d%n", &prev, &offset) != 1) {
    perror ("Failure to scan");
    exit (1);
}
while (sscanf (line + offset, "%d%n", &next, &off) == 1) {
    offset += off;
    if (prev > next) {
        sorted = false;
    }
    prev = next;
}
printf ("%d\n", sorted ? 1 : 0);

We use [sscanf] to extract integers from the line of input, comparing each integer (except the first) with the previous one.

Find the full program on GitHub.

Go

Here, we have read in the data into a string line:

list   := strings . Split (line, " ")

sorted := true
for i := 1; sorted && i < len (list); i ++ {
    prev, _ := strconv . Atoi (list [i - 1])
    next, _ := strconv . Atoi (list [i])
    sorted = prev <= next
}

if (sorted) {
    fmt . Println (1)
} else {
    fmt . Println (0)
}

We're using Atoi to map a string into an integer, as Go doesn't automatically convert strings into integer.

It's a pity Go lacks a ternary operator.

Find the full program on GitHub.

Java

With line a string containing the input, we get a solution very similar to the Go solution:

String [] list = line . split (" ");
boolean sorted = true;
for (int i = 1; sorted && i < list . length; i ++) { 
    sorted = Integer . parseInt (list [i - 1]) <= 
             Integer . parseInt (list [i]); 
}
System . out . println (sorted ? 1 : 0);

Find the full program on GitHub.

Lua

Lua lacks a split function, nor does it have something like scanf. So, we're using pattern matching to extract numbers from the input line line:

local sorted = 1
local prev   = nil
for next in line : gmatch ("[0-9]+") do
    if prev ~= nil and prev > next then
        sorted = 0
    end
    prev = next
end
print (sorted)

Find the full program on GitHub.

Node.js

Our Node.js solution also uses pattern matching to extract the numbers from the line of input, and uses reduce to loop over the array of numbers, checking if all elements are in order:

console . log (line . match (/[0-9]+/gi) . reduce ((sorted, _, i, list) => {
    if (i > 0 && list [i - 1] > list [i]) {sorted = 0}
    return sorted},
    1) 
)

Find the full program on GitHub.

Pascal

In Pascal, we can read in the numbers one by one, allowing us to easily compare consecutive numbers:

var
    prev, next: integer;
    sorted: integer;

begin
    sorted := 1;
    read (prev);
    while not eoln do begin
        read (next);
        if prev > next then begin
            sorted := 0;
        end;
        prev := next;
    end;
    readln ();
    writeln (sorted);
end.

Find the full program on GitHub.

Perl

In Perl, we also use pattern matching to extract the numbers from the input, which is in $_. Unlike most other solutions, we don't require an additional sorted variable. Instead, we use grep to find out whether any pairs of numbers are in unsorted order:

my @list = /[0-9]+/g;
say grep ({$list [$_ - 1] > $list [$_]} 1 .. $#list) ? 0 : 1

Find the full program on GitHub.

Python

In Python, we just split the input, and loop over the resulting list:

list = line . split (" ")
sorted = 1
for i in range (1, len (list)):
    if list [i - 1] > list [i]:
        sorted = 0
print (sorted)

Find the full program on GitHub.

R

In R, we can use strsplit to split the input, and as.numeric to map strings to numbers. Then it's our familiar loop:

parts  <- strsplit (line, " ")
list   <- as.numeric (parts [[1]])
sorted <- 1
if (length (list) > 1) {
    for (i in 2 : length (list)) {
        if (list [i - 1] > list [i]) {
            sorted <- 0
        }
    }
}       
cat (sorted, "\n")

Note we do need a seperate check for the length of the list. If we have a one element list, the loop for (i in 2 : length (list)) { .. } would be executed twice: first with i = 2, then with i = 1. Which would not be what we want.

Find the full program on GitHub.

Ruby

Our Ruby solution is similar to other solutions. We use map.with_index to iterate over the list. We're only interested in the index, so we use _ to signal we're not interested in the element.

sorted = 1
list = line . strip() . split(" ")
list . map . with_index do
    | _, i |
    if i > 0 && list [i - 1] > list [i] then
        sorted = 0
    end
end
puts (sorted)

Find the full program on GitHub.

Scheme

Our Scheme solution looks very different. Iterating over lists isn't very Scheme-like. Instead, we use a recursive method:

This leads the following function:

(define (is-sorted list)
    (cond ((< (length list) 2)                     1)
          ((> (list-ref list 0) (list-ref list 1)) 0)
          (else (is-sorted (cdr list))))
)

After having read the input into a line line, we call the function above as:

(display (is-sorted (map-in-order string->number (string-split line #\ ))))
(newline)

string-split splits the input line on spaces (\#). We map the resulting strings to numbers by applying string-number on each element (due to map-in-order). The resulting list of numbers is then passed to is-sorted, and its return value is printed.

Find the full program on GitHub.

Tcl

Our Tcl solution looks like many other solutions:

set list [split $line " "]
set result 1
for {set i 1} {$i < [llength $list]} {incr i} {
    if {[lindex $list [expr $i - 1]] > [lindex $list $i]} {
        set result 0
        break
    }
}
puts $result

Find the full program on GitHub.


Please leave any comments as a GitHub issue.