diff --git a/.glotter.yml b/.glotter.yml index 41a723e02..8d8d5684e 100644 --- a/.glotter.yml +++ b/.glotter.yml @@ -1505,16 +1505,6 @@ projects: name: "bubblesort" search: "bubble_sort" replace: "selection_sort" - sleepsort: - words: - - "sleep" - - "sort" - use_tests: - name: "bubblesort" - search: "bubble_sort" - replace: "sleep_sort" - repeat: - sleep_sort_valid: 10 transposematrix: words: - "transpose" diff --git a/archive/a/algol68/sleep-sort.alg b/archive/a/algol68/sleep-sort.alg deleted file mode 100644 index ffd0715df..000000000 --- a/archive/a/algol68/sleep-sort.alg +++ /dev/null @@ -1,166 +0,0 @@ -MODE PARSEINT_RESULT = STRUCT(BOOL valid, INT value, STRING leftover); -MODE PARSEINTLIST_RESULT = STRUCT(BOOL valid, REF []INT values); - -PROC parse int = (REF STRING s) PARSEINT_RESULT: -( - BOOL valid := FALSE; - REAL r := 0.0; - INT n := 0; - STRING leftover; - - # Associate string with a file # - FILE f; - associate(f, s); - - # On end of input, exit if valid number not seen. Otherwise ignore it # - on logical file end(f, (REF FILE dummy) BOOL: - ( - IF NOT valid THEN done FI; - TRUE - ) - ); - - # Exit if value error # - on value error(f, (REF FILE dummy) BOOL: done); - - # Convert string to real number # - get(f, r); - - # If real number is in range of an integer, convert to integer. Indicate integer is valid if same as real # - IF ABS r <= max int - THEN - n := ENTIER(r); - valid := (n = r) - FI; - - # Get leftover string # - get(f, leftover); - -done: - close(f); - PARSEINT_RESULT(valid, n, leftover) -); - -PROC count list items = (STRING s) INT: -( - INT count := 1; - FOR k TO UPB s - DO - IF s[k] = "," - THEN - count +:= 1 - FI - OD; - - count -); - -PROC parse int list = (REF STRING s) PARSEINTLIST_RESULT: -( - BOOL valid := FALSE; - STRING leftover := s; - INT num list items = count list items(s); - HEAP [num list items]INT values; - - # Repeat while valid value # - FOR k TO num list items - DO - # Get next integer value and update leftover string # - PARSEINT_RESULT result = parse int(leftover); - valid := valid OF result; - leftover := leftover OF result; - - # Append the integer value to list # - values[k] := value OF result; - - # Do nothing if end of string # - IF leftover = "" - THEN - SKIP - # Skip comma if leftover string starts with comma # - ELIF leftover[1] = "," - THEN - leftover := leftover[2:] - # Otherwise indicate invalid # - ELSE - valid := FALSE - FI - UNTIL NOT valid - OD; - - PARSEINTLIST_RESULT(valid, values) -); - -PROC usage = VOID: ( - printf(($gl$, "Usage: please provide a list of at least two integers to sort in the format ""1, 2, 3, 4, 5""")) -); - -COMMENT -Algol68 does not have any type of mechanism to sleep for a specified time, -nor do threads seems to work reliably. Instead, just monitor the clock -and store values as each sleep time elapses -COMMENT -PROC sleep sort = (REF []INT sleep times) REF []INT: -( - INT n := UPB sleep times; - HEAP [n]INT working sleep times := sleep times; - HEAP [n]INT values; - INT num values := 0; - - # For each sleep time that is not complete, when sleep time expires, append the # - # sleep time to the list of values and remove the sleep time from the list # - REAL start := seconds; - DO - REAL current := seconds; - INT num sleep times := 0; - FOR k TO n - DO - IF (current - start) >= working sleep times[k] - THEN - num values +:= 1; - values[num values] := working sleep times[k] - ELSE - num sleep times +:= 1; - working sleep times[num sleep times] := working sleep times[k] - FI - OD; - - n := num sleep times - UNTIL num sleep times < 1 - OD; - - values -); - -PROC show list values = (REF []INT values) VOID: -( - INT n = UPB values; - FOR k TO n - DO - IF k > 1 - THEN - print(", ") - FI; - - print(whole(values[k], 0)) - OD; - - IF n > 0 - THEN - print(newline) - FI -); - -# Parse 1st command-line argument # -STRING s := argv(4); -PARSEINTLIST_RESULT list result := parse int list(s); -REF []INT sleep times := values OF list result; -IF NOT valid OF list result OR UPB sleep times < 2 -THEN - usage; - stop -FI; - -# Do sleep sort and show results # -REF []INT values := sleep sort(sleep times); -show list values(values) diff --git a/archive/a/awk/sleep-sort.awk b/archive/a/awk/sleep-sort.awk deleted file mode 100644 index 0350265ca..000000000 --- a/archive/a/awk/sleep-sort.awk +++ /dev/null @@ -1,79 +0,0 @@ -@load "time" - -function usage() { - print "Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\"" - exit(1) -} - -function str_to_number(s) { - return (s ~ /^\s*[+-]*[0-9]+\s*$/) ? s + 0 : "ERROR" -} - -function str_to_array(s, arr, str_arr, idx, result) { - split(s, str_arr, ",") - for (idx in str_arr) { - result = str_to_number(str_arr[idx]) - if (result == "ERROR") { - delete arr - arr[1] = "ERROR" - break - } else { - arr[idx] = result - } - } -} - -# Awk does not have threads. However, it does have a functions to get the -# current system time and sleep with fractions of a second precision. Use those -# to monitor the elapsed time, and use that to sort the array -function sleep_sort(arr, arr_len, curr_time, start_time, elapsed_time, i, t, num_sorted) { - # Get initial time - start_time = gettimeofday() - - # Indicate no sorted elements yet - num_sorted = 0 - - # Repeat unit array is sorted - while (num_sorted < arr_len) { - # When elapsed time for array element expires, swap it from the unsorted to the - # sorted part of the array - elapsed_time = gettimeofday() - start_time - for (i = num_sorted + 1; i <= arr_len; i++) { - if (elapsed_time >= arr[i]) { - num_sorted++ - t = arr[i] - arr[i] = arr[num_sorted] - arr[num_sorted] = t - } - } - - sleep(0.5) - } -} - -function show_array(arr, idx, s) { - s = "" - for (idx in arr) { - if (s) { - s = s ", " - } - s = s arr[idx] - } - - print s -} - -BEGIN { - if (ARGC < 2) { - usage() - } - - str_to_array(ARGV[1], arr) - arr_len = length(arr) - if (!arr_len || arr_len < 2) { - usage() - } - - sleep_sort(arr, arr_len) - show_array(arr) -} diff --git a/archive/b/beef/SleepSort.bf b/archive/b/beef/SleepSort.bf deleted file mode 100644 index fb57ae877..000000000 --- a/archive/b/beef/SleepSort.bf +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using System.Collections; -using System.Threading; - -namespace SleepSort; - -class Program -{ - public static void Usage() - { - Console.WriteLine( - """ - Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5" - """ - ); - Environment.Exit(0); - } - - public static Result ParseInt(StringView str) - where T : IParseable - { - StringView trimmedStr = scope String(str); - trimmedStr.Trim(); - - // T.Parse ignores single quotes since they are treat as digit separators -- e.g. 1'000 - if (trimmedStr.Contains('\'')) - { - return .Err; - } - - return T.Parse(trimmedStr); - } - - public static Result ParseIntList(StringView str, List arr) - where T: IParseable - { - arr.Clear(); - for (StringView item in str.Split(',')) - { - switch (ParseInt(item)) - { - case .Ok(let val): - arr.Add(val); - - case .Err: - return .Err; - } - } - - return .Ok; - } - - public static void SleepSort(List arr) - { - // Initialize temporary array to hold sleep values - List tempArr = scope .(); - - // Create and start threads - Monitor monitor = scope .(); - List threads = scope .(); - for (int32 sleepVal in arr) - { - Thread thread = new .(new [=sleepVal, &tempArr, &monitor] () => { - Thread.Sleep(sleepVal * 1000); - using (monitor.Enter()) - { - tempArr.Add(sleepVal); - } - }); - threads.Add(thread); - thread.Start(false); - } - - // Wait for threads to complete - for (Thread thread in threads) - { - thread.Join(); - delete thread; - } - - // Copy temporary array to array to sort - arr.Clear(); - tempArr.CopyTo(arr); - } - - public static void ShowList(List arr) - { - String line = scope .(); - for (T val in arr) - { - if (!line.IsEmpty) - { - line += ", "; - } - - line.AppendF("{}", val); - } - - Console.WriteLine(line); - } - - public static int Main(String[] args) - { - if (args.Count < 1) - { - Usage(); - } - - List arr = scope .(); - switch (ParseIntList(args[0], arr)) - { - case .Ok: - if (arr.Count < 2) - { - Usage(); - } - case .Err: - Usage(); - } - - SleepSort(arr); - ShowList(arr); - return 0; - } -} diff --git a/archive/c/c-plus-plus/sleep-sort.cpp b/archive/c/c-plus-plus/sleep-sort.cpp deleted file mode 100644 index 534f7993d..000000000 --- a/archive/c/c-plus-plus/sleep-sort.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ranges = std::ranges; -namespace views = std::views; - -[[noreturn]] void usage() { - std::cerr - << "Usage: please provide a list of at least two integers to sort " - "in the format \"1, 2, 3, 4, 5\"\n"; - std::exit(1); -} - -static constexpr std::string_view ws = " \t\n\r\f\v"; -constexpr std::string_view trim(std::string_view s) { - const auto start = s.find_first_not_of(ws); - if (start == std::string_view::npos) return ""; - s.remove_prefix(start); - - const auto end = s.find_last_not_of(ws); - s.remove_suffix(s.size() - 1 - end); - return s; -} - -std::optional to_int(std::string_view s) { - int value{}; - auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), value); - return (ec == std::errc{} && ptr == s.data() + s.size()) - ? std::make_optional(value) - : std::nullopt; -} - -std::optional> parse_vec(std::string_view s) { - auto pipe = s | views::split(',') | views::transform([](auto&& r) { - return std::string_view{ - std::addressof(*ranges::begin(r)), - static_cast(ranges::distance(r))}; - }) | - views::transform(trim) | views::transform(to_int); - - std::vector out; - for (auto&& opt : pipe) { - if (!opt) return std::nullopt; - out.push_back(*opt); - } - return out.size() < 2 ? std::nullopt : std::make_optional(out); -} - -void sleep_sort_worker(int value, std::vector& output, std::mutex& mtx) { - std::this_thread::sleep_for(std::chrono::seconds(value)); - - { - std::lock_guard lock(mtx); - output.push_back(value); - } -} - -int main(int argc, char* argv[]) { - if (argc != 2) usage(); - - std::string_view input = argv[1]; - auto numbers = parse_vec(input); - if (!numbers) usage(); - - std::vector sorted; - sorted.reserve(numbers->size()); - - std::mutex mtx; - std::vector threads; - threads.reserve(numbers->size()); - - for (int n : *numbers) { - threads.emplace_back(sleep_sort_worker, n, std::ref(sorted), - std::ref(mtx)); - } - - for (auto& t : threads) t.join(); - - for (const char* sep = ""; int val : sorted) { - std::cout << std::exchange(sep, ", ") << val; - } - std::cout << "\n"; -} \ No newline at end of file diff --git a/archive/c/c-sharp/SleepSort.cs b/archive/c/c-sharp/SleepSort.cs deleted file mode 100644 index 6fbf0b225..000000000 --- a/archive/c/c-sharp/SleepSort.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.Threading.Tasks; - -public class SleepSort -{ - public static void ErrorAndExit() - { - Console.WriteLine("Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\""); - Environment.Exit(1); - } - - public static void Main(string[] args) - { - if (args.Length != 1) - ErrorAndExit(); - try - { - var xs = args[0].Split(',').Select(i => Int32.Parse(i.Trim())).ToList(); - if (xs.Count <= 1) - ErrorAndExit(); - - Queue sortedXs = new Queue(); - - Task.WaitAll(xs.Select(x => - Task.Delay(x * 1000).ContinueWith(_ => sortedXs.Enqueue(x)) - ).ToArray()); - - Console.WriteLine(string.Join(", ", sortedXs)); - } - catch - { - ErrorAndExit(); - } - } -} \ No newline at end of file diff --git a/archive/c/c/sleep-sort.c b/archive/c/c/sleep-sort.c deleted file mode 100644 index 3fae73afa..000000000 --- a/archive/c/c/sleep-sort.c +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include -#include -#include -#include - -pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER; -int *global_sorted; -int global_index = 0; -int global_total; - -typedef struct -{ - int number; -} ThreadPayload; - -void *sortNumber(void *args) -{ - ThreadPayload *payload = (ThreadPayload *)args; - const int number = payload->number; - - sleep(number); // Sleep for number seconds - - pthread_mutex_lock(&print_mutex); - global_sorted[global_index++] = number; - pthread_mutex_unlock(&print_mutex); - - free(payload); - return NULL; -} - -void parseInput(const char *input, int **arr, int *n) -{ - char *token; - char *inputCopy = strdup(input); - token = strtok(inputCopy, ","); - - while (token != NULL) - { - (*arr)[(*n)++] = atoi(token); - token = strtok(NULL, ","); - } - - free(inputCopy); -} - -int main(int argc, char *argv[]) -{ - if (argc != 2) - { - printf("Usage: please provide a list of at least two integers to sort " - "in the format \"1, 2, 3, 4, 5\"\n"); - return 1; - } - - const char *input = argv[1]; - if (strlen(input) == 0 || input[0] == ' ') - { - printf("Usage: please provide a list of at least two integers to sort " - "in the format \"1, 2, 3, 4, 5\"\n"); - return 1; - } - - int *arr = malloc(100 * sizeof(int)); - int n = 0; - - parseInput(input, &arr, &n); - - if (n < 2) - { - printf("Usage: please provide a list of at least two integers to sort " - "in the format \"1, 2, 3, 4, 5\"\n"); - free(arr); - return 1; - } - - global_sorted = malloc(n * sizeof(int)); - global_total = n; - - pthread_t *threads = malloc(n * sizeof(pthread_t)); - - for (int i = 0; i < n; i++) - { - ThreadPayload *payload = malloc(sizeof(ThreadPayload)); - payload->number = arr[i]; - pthread_create(&threads[i], NULL, sortNumber, (void *)payload); - } - - for (int i = 0; i < n; i++) - pthread_join(threads[i], NULL); - - for (int i = 0; i < n; i++) - printf("%d%s", global_sorted[i], (i < n - 1) ? ", " : ""); - printf("\n"); - - free(arr); - free(threads); - free(global_sorted); - - return 0; -} diff --git a/archive/c/cobol/sleep-sort.cbl b/archive/c/cobol/sleep-sort.cbl deleted file mode 100644 index 17e538817..000000000 --- a/archive/c/cobol/sleep-sort.cbl +++ /dev/null @@ -1,142 +0,0 @@ -identification division. -program-id. sleep-sort. - -data division. -working-storage section. -01 argument-string pic x(32768). -01 current-token pic x(64). -01 scan-ptr binary-long value 1. -01 temp-ptr binary-long. - -01 pipe-fds-table. - 05 pipe-read-fd binary-long. - 05 pipe-write-fd binary-long. - -01 process-vars. - 05 pid binary-long. - 05 child-val binary-long. - 05 children-spawned binary-long value 0. - 05 children-done binary-long value 0. - -01 io-vars. - 05 write-buffer pic x(32). - 05 pipe-buffer pic x(128). - 05 formatted-val pic -(10)9. - 05 bytes-read binary-long. - 01 nl pic x value x'0a'. - -procedure division. -main. - accept argument-string from command-line - if argument-string = spaces perform show-usage. - - perform validate-input-count - - call "pipe" using pipe-fds-table returning pid - if pid = -1 - display "Error: Could not create pipe." - stop run 1 - end-if - - perform spawn-sleepers - - call "close" using by value pipe-write-fd - - perform collect-results - - display space - stop run. - -validate-input-count. - move 1 to temp-ptr - move 0 to children-spawned - perform until temp-ptr > function length(argument-string) - move spaces to current-token - unstring argument-string delimited by "," - into current-token with pointer temp-ptr - - if function trim(current-token) not = spaces - if function test-numval(function trim(current-token)) <> 0 - perform show-usage - end-if - add 1 to children-spawned - end-if - end-perform - - if children-spawned < 2 perform show-usage. - -spawn-sleepers. - move 1 to scan-ptr - perform until scan-ptr > function length(argument-string) - move spaces to current-token - unstring argument-string delimited by "," - into current-token with pointer scan-ptr - - if function trim(current-token) not = spaces - move function numval(current-token) to child-val - call "fork" returning pid - - evaluate true - when pid = 0 - call "close" using by value pipe-read-fd - - *> Wait for parent to finish loop - call "C$SLEEP" using 1 - - if child-val < 0 move 0 to child-val end-if - call "C$SLEEP" using child-val - - move child-val to formatted-val - string function trim(formatted-val) nl - delimited by size into write-buffer - - call "write" using by value pipe-write-fd - by reference write-buffer - by value function length(function trim(write-buffer)) - call "exit" using by value 0 - - when pid = -1 - *> Fork failed (e.g. out of processes) - subtract 1 from children-spawned - end-evaluate - end-if - end-perform. - -collect-results. - perform until children-done >= children-spawned - move spaces to pipe-buffer - call "read" using by value pipe-read-fd - by reference pipe-buffer - by value 128 - returning bytes-read - - if bytes-read > 0 - perform parse-pipe-chunk - else - *> Pipe closed or error - exit perform - end-if - end-perform. - -parse-pipe-chunk. - move 1 to temp-ptr - perform until temp-ptr > bytes-read - move spaces to current-token - unstring pipe-buffer delimited by nl - into current-token with pointer temp-ptr - - if current-token not = spaces - add 1 to children-done - display function trim(current-token) with no advancing - - if children-done < children-spawned - display ", " with no advancing - end-if - call "fflush" using by value 0 - end-if - end-perform. - -show-usage. - display 'Usage: please provide a list of at least two ' - 'integers to sort in the format "1, 2, 3, 4, 5"' - stop run 1. diff --git a/archive/c/commodore-basic/sleep-sort.bas b/archive/c/commodore-basic/sleep-sort.bas deleted file mode 100644 index c7092cc12..000000000 --- a/archive/c/commodore-basic/sleep-sort.bas +++ /dev/null @@ -1,106 +0,0 @@ -10 DIM A(100) -20 GOSUB 2000: REM Get array -25 REM Error if invalid, not end of input/value, or less that 2 items -30 IF V = 0 OR C >= 0 OR NA < 2 THEN GOTO 200 -40 GOSUB 3000: REM Perform sleep sort -50 GOSUB 3500: REM Show array -60 END -200 Q$ = CHR$(34): REM quote -210 PRINT "Usage: please provide a list of at least two integers to sort "; -220 PRINT "in the format "; Q$; "1, 2, 3, 4, 5"; Q$ -230 END -1000 REM Read input value one character at a time since Commodore BASIC -1001 REM has trouble reading line from stdin properly -1002 REM NR = number -1003 REM V = 1 if valid number, 0 otherwise -1004 REM C = -2 if end of input, -1 if end of value, -1005 REM 32 if whitespace, ASCII code of last character otherwise -1006 REM Initialize -1010 NR = 0 -1020 V = 0 -1030 S = 1 -1035 REM Loop while leading spaces -1040 GOSUB 1500 -1050 IF C = 43 OR C = 45 THEN GOTO 1100: REM + or - -1060 IF C >= 48 AND C <= 57 THEN GOTO 1150: REM 0 to 9 -1070 IF C = 32 THEN GOTO 1040: REM whitespace -1080 RETURN: REM other character -1085 REM Loop while sign -1090 GOSUB 1500 -1100 IF C = 43 THEN GOTO 1090: REM + -1110 IF C >= 48 AND C <= 57 THEN GOTO 1150: REM 0 to 9 -1120 IF C <> 45 THEN RETURN: REM not - -1130 S = -S -1140 GOTO 1090 -1145 REM Set valid flag -1150 V = 1 -1155 REM Loop while digits -1160 NR = (ABS(NR) * 10 + C - 48) * S -1170 GOSUB 1500 -1180 IF C >= 48 AND C <= 57 THEN GOTO 1160: REM 0 to 9 -1185 REM Loop while trailing spaces -1190 IF C < 0 OR C <> 32 THEN RETURN: REM end character or not whitespace -1200 GOSUB 1500 -1210 GOTO 1180 -1500 REM Get input character -1501 REM A$ = input character -1502 REM C = One of the following: -1502 REM - -1 if end of value -1503 REM - -2 if end of input -1504 REM - 32 if whitespace -1505 REM - ASCII code otherwise -1510 GET A$ -1520 C = ASC(A$) -1530 IF C = 13 THEN C = -1 -1540 IF C = 255 THEN C = -2 -1550 IF C = 9 OR C = 10 THEN C = 32 -1560 RETURN -2000 REM Read array value -2001 REM A contains array value -2002 REM NA contains length of array -2003 REM V = 1 if valid number, 0 otherwise -2004 REM C = -2 if end of input, -1 if end of value, -2005 REM 32 if whitespace, ASCII code of last character otherwise -2006 REM Initialize -2010 NA = 0 -2020 GOSUB 1000: REM Read input value -2030 IF V = 0 THEN RETURN: REM invalid -2040 NA = NA + 1 -2050 A(NA) = NR -2060 IF C < 0 THEN RETURN: REM end of input or value -2070 IF C = 44 THEN GOTO 2020: REM comma, get next value -2080 V = 0 -2090 RETURN -3000 REM Sleep sort -3001 REM Commodore Basic does not support sleep or threads, so this has -3002 REM to be done by monitoring the system timer, TI, which counts in -3003 REM 1/60th of a second increments. -3004 REM Inputs: -3005 REM - A contains array to sort -3006 REM - NA contains size of array -3007 REM Outputs: A contains sorted array -3010 NU = 0: REM Number of expired sleep timers -3020 T0 = TI -3030 TE = (TI - T0) / 60: REM Elapsed time -3040 IF NU >= NA THEN RETURN: REM All sleep timer expired -3050 FOR I = NU + 1 TO NA: REM From first unexpired entry to last -3055 REM If sleep timer expired, swipe expired with this unexpired -3060 IF TE < A(I) THEN GOTO 3110 -3070 NU = NU + 1 -3080 T = A(I) -3090 A(I) = A(NU) -3100 A(NU) = T -3110 NEXT I -3220 GOTO 3030 -3500 REM Display array -3501 REM A contains array -3502 REM NA contains size of array -3510 IF NA < 1 THEN GOTO 3590 -3520 FOR I = 1 TO NA -3530 S$ = STR$(A(I)) -3540 IF A(I) >= 0 THEN S$ = MID$(S$, 2): REM strip leading space -3550 PRINT S$; -3560 IF I < NA THEN PRINT ", "; -3570 NEXT I -3580 PRINT -3590 RETURN diff --git a/archive/d/dart/sleep-sort.dart b/archive/d/dart/sleep-sort.dart deleted file mode 100644 index 94c2dfa82..000000000 --- a/archive/d/dart/sleep-sort.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'dart:async'; - -void main(List args) async { - - if (args.length == 0 || args[0].isEmpty || args[0].split(",").length == 1) { - print('Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5"'); - } else { - List userInput = args[0].split(",").map((str) => int.tryParse(str)) - .takeWhile((test) => test != null) - .toList(); - - List sorted = await sleepsort(userInput); - - print(sorted); - } -} - -Future> sleepsort(Iterable input) async { - List sorted = List(); - await Future.wait(input.map((i) => Future.delayed(Duration(seconds: i), () => sorted.add(i)))); - return Future.value(sorted); -} diff --git a/archive/e/euphoria/sleep_sort.eu b/archive/e/euphoria/sleep_sort.eu deleted file mode 100644 index 5b94030bf..000000000 --- a/archive/e/euphoria/sleep_sort.eu +++ /dev/null @@ -1,131 +0,0 @@ -include std/io.e -include std/types.e -include std/text.e -include std/get.e as stdget -include std/sequence.e -include std/os.e - --- Indices for value() return value -enum VALUE_ERROR_CODE, VALUE_VALUE, VALUE_NUM_CHARS_READ - --- Indices for parse_int() return value -enum PARSE_INT_VALID, PARSE_INT_VALUE - -function parse_int(sequence s) - -- Trim off whitespace and parse string - s = trim(s) - sequence result = stdget:value(s,, GET_LONG_ANSWER) - - -- Error if any errors, value is not an integer, or any leftover characters - boolean valid = ( - result[VALUE_ERROR_CODE] = GET_SUCCESS - and integer(result[VALUE_VALUE]) - and result[VALUE_NUM_CHARS_READ] = length(s) - ) - - -- Get value if invalid - integer value = 0 - if valid - then - value = result[VALUE_VALUE] - end if - - return {valid, value} -end function - --- Indices for parse_int_list() return value -enum PARSE_INT_LIST_VALID, PARSE_INT_LIST_VALUES - -function parse_int_list(sequence s) - -- Split string on comma - sequence list = split(s, ",") - - -- Parse each item - integer valid = FALSE - sequence values = {} - for n = 1 to length(list) - do - sequence result = parse_int(list[n]) - valid = result[PARSE_INT_VALID] - values &= result[PARSE_INT_VALUE] - if not valid - then - exit - end if - end for - - return {valid, values} -end function - -procedure usage() - puts( - STDOUT, - "Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\"\n" - ) - abort(0) -end procedure - -procedure show_list_values(sequence values) - if length(values) > 0 - then - sequence format = repeat_pattern("%d, ", length(values)) - sequence s = sprintf(format[1..$-2], values) - printf(STDOUT, "%s\n", {s}) - end if -end procedure - --- Although Euphoria claims to have a cooperative multi-tasking system, --- I never could get this to work. Instead, just monitor the clock --- and store values as each sleep time elapses -function sleep_sort(sequence sleep_times) - -- Initialize values - sequence values = {} - - -- Wait for all sleep times are complete - atom start = time() - while TRUE - do - -- For each sleep time that is not complete, when sleep time expires, append the - -- sleep time to the list of values and remove the sleep time from the list - atom current = time() - sequence new_sleep_times = {} - for k = 1 to length(sleep_times) - do - if (current - start) >= sleep_times[k] - then - values &= sleep_times[k] - else - new_sleep_times &= sleep_times[k] - end if - end for - - sleep_times = new_sleep_times - if length(sleep_times) < 1 - then - exit - end if - - sleep(0.5) - end while - - return values -end function - --- Check 1st command-line argument -sequence argv = command_line() -if length(argv) < 4 or length(argv[4]) = 0 -then - usage() -end if - --- Parse 1st command-line argument -sequence result = parse_int_list(argv[4]) -sequence sleep_times = result[PARSE_INT_LIST_VALUES] -if not result[PARSE_INT_LIST_VALID] or length(sleep_times) < 2 -then - usage() -end if - --- Do sleep sort and show results -sequence values = sleep_sort(sleep_times) -show_list_values(values) diff --git a/archive/f/f-sharp/SleepSort.fs b/archive/f/f-sharp/SleepSort.fs deleted file mode 100644 index 69bcc4942..000000000 --- a/archive/f/f-sharp/SleepSort.fs +++ /dev/null @@ -1,54 +0,0 @@ -open System -open System.Collections.Concurrent - -module SleepSort = - let run numbers = - let results = ConcurrentQueue() - - let tasks = - numbers - |> List.map (fun n -> - async { - do! Async.Sleep(n * 100) - results.Enqueue n - }) - - tasks |> Async.Parallel |> Async.RunSynchronously |> ignore - results |> Seq.toList |> List.map string |> String.concat ", " |> Ok - -module Result = - let toOption = - function - | Ok x -> Some x - | Error _ -> None - -module Helpers = - let private (|IntList|_|) (s: string) = - let ns = - s.Split(',', StringSplitOptions.RemoveEmptyEntries) - |> Array.toList - |> List.map (fun p -> - match Int32.TryParse(p.Trim()) with - | true, n -> Ok n - | false, _ -> Error $"Invalid integer: '{p}'") - |> List.choose Result.toOption - - if ns.Length >= 2 then Some ns else None - - let parseArgs argv = - match argv with - | [| IntList numbers |] -> Ok numbers - | _ -> Error "Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\"" - - let handleResult = - function - | Ok result -> - printfn "%s" result - 0 - | Error msg -> - eprintfn "%s" msg - 1 - -[] -let main argv = - argv |> Helpers.parseArgs |> Result.bind SleepSort.run |> Helpers.handleResult diff --git a/archive/g/go/sleep-sort.go b/archive/g/go/sleep-sort.go deleted file mode 100644 index 5e691e1ad..000000000 --- a/archive/g/go/sleep-sort.go +++ /dev/null @@ -1,116 +0,0 @@ -package main - -import ( - "fmt" - "os" - "strconv" - "strings" - "time" -) - -// Time to mutiply each number by when sleeping -// 15ms is hopefully a happy middle ground between flaky and slow sorting -const sleepFactor = 15 * time.Millisecond -const errorMessage = `Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5"` - -// Parses string of comma-space separated integers into slice of ints -// Returns non-nil error if numbers are malformed or if there are fewer than 2 numbers -func parseInput(input string) ([]int, error) { - splitInput := strings.Split(input, ", ") - if len(splitInput) < 2 { - return nil, fmt.Errorf("Input '%s' does not contain at least two numbers", splitInput) - } - - nums := make([]int, len(splitInput)) - for i, s := range splitInput { - n, err := strconv.Atoi(s) - if err != nil { - return nil, err - } - nums[i] = n - } - return nums, nil -} - -// Sends the given number to the given channel after the given amount of time -// Blocks the current goroutine until send is completed -func waitAndSend(num int, wait time.Duration, c chan int) { - time.Sleep(wait) - c <- num -} - -// Finds the minimum int in a slice. -// Panics on an empty slice -func minInt(nums []int) int { - min := nums[0] - for _, n := range nums { - if n < min { - min = n - } - } - return min -} - -// Creates a new sorted slice of ints from the input -// Internally makes len(unsorted) goroutines -func sleepSort(unsorted []int) []int { - min := minInt(unsorted) - - c := make(chan int) - for _, n := range unsorted { - // Shift the numbers by the minimum value and multiply by the sleepFactor - // This means the smallest number will have no sleep - // This is necessary to accomodate negative numbers as you can't sleep - // for a negative amount of time. - // If all numbers are positive, it reduces the runtime by about min * sleepFactor - sleepTime := time.Duration(n-min) * sleepFactor - - go waitAndSend(n, sleepTime, c) - } - - sorted := make([]int, len(unsorted)) - for i := range unsorted { - sorted[i] = <-c - } - - return sorted -} - -// Join a slice of ints into a comma-space separated string -func formatSlice(nums []int) string { - strs := make([]string, len(nums)) - - for i, n := range nums { - strs[i] = strconv.Itoa(n) - } - - return strings.Join(strs, ", ") -} - -// Takes a string of comma-space separated integers and returns -// a new comma-space separated string with the values in ascending order. -func parseAndSort(input string) (string, error) { - unsorted, err := parseInput(input) - if err != nil { - return "", err - } - - sorted := sleepSort(unsorted) - return formatSlice(sorted), nil -} - -func main() { - // Must supply an argument - if len(os.Args) < 2 { - fmt.Println(errorMessage) - os.Exit(1) - } - - output, err := parseAndSort(os.Args[1]) - if err != nil { - fmt.Println(errorMessage) - os.Exit(1) - } else { - fmt.Println(output) - } -} diff --git a/archive/j/java/SleepSort.java b/archive/j/java/SleepSort.java deleted file mode 100644 index 13ab24900..000000000 --- a/archive/j/java/SleepSort.java +++ /dev/null @@ -1,71 +0,0 @@ -import java.time.Duration; -import java.util.*; -import java.util.concurrent.*; -import java.util.stream.Collectors; - -public class SleepSort { - - public static void main(String[] args) { - if (args.length != 1 || args[0].isBlank()) { - usage(); - } - - List numbers = parse(args[0]); - if (numbers.size() < 2) { - usage(); - } - - List sorted = sleepSort(numbers); - - System.out.println(format(sorted)); - } - - private static List sleepSort(List input) { - List sortedList = Collections.synchronizedList(new ArrayList<>()); - - ExecutorService executor = Executors.newCachedThreadPool(); - - CountDownLatch latch = new CountDownLatch(input.size()); - - for (int n : input) { - executor.submit(() -> { - try { - Thread.sleep(n * 100L); - sortedList.add(n); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } finally { - latch.countDown(); - } - }); - } - - try { - latch.await(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - - executor.shutdown(); - - return sortedList; - } - - private static List parse(String input) { - try { - return Arrays.stream(input.split(",")).map(String::trim).map(Integer::parseInt).toList(); - } catch (Exception e) { - usage(); - return List.of(); // Unreachable - } - } - - private static String format(List list) { - return list.stream().map(String::valueOf).collect(Collectors.joining(", ")); - } - - private static void usage() { - System.out.println("Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\""); - System.exit(1); - } -} \ No newline at end of file diff --git a/archive/j/javascript/sleep-sort.js b/archive/j/javascript/sleep-sort.js deleted file mode 100644 index 51a160c62..000000000 --- a/archive/j/javascript/sleep-sort.js +++ /dev/null @@ -1,43 +0,0 @@ -function sleepSort(arr) { - const sortedArray = []; - - function sleepSortHelper(item) { - setTimeout(() => { - sortedArray.push(item); - if (sortedArray.length === arr.length) { - console.log(sortedArray.join(", ")); - } - }, item*1000); - } - - arr.forEach((item) => { - if (item < 0) { - console.log(error_msg); - return; - } - sleepSortHelper(item); - }); -} - -const error_msg = - 'Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5"'; - -function sortNumbers(input) { - const numberList = input.split(",").map((item) => parseInt(item.trim())); - - if (numberList.length < 2) { - console.log(error_msg); - } else if (numberList.some(isNaN)) { - console.log(error_msg); - } else { - sleepSort(numberList); - } -} - -const input = process.argv[2]; - -if (!input) { - console.log(error_msg); -} else { - sortNumbers(input); -} diff --git a/archive/m/mathematica/sleep-sort.nb b/archive/m/mathematica/sleep-sort.nb deleted file mode 100644 index 9602a89e3..000000000 --- a/archive/m/mathematica/sleep-sort.nb +++ /dev/null @@ -1,32 +0,0 @@ -ClearAll[sleepSortMain, sleepSort]; - -sleepSort[l_List, t_: 0.1] := - Flatten[Last[Reap[Map[(Pause[t #]; Sow[#]) &, l]]]]; - -$usage = "Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\""; - -sleepSortMain[str_String] := Module[{nums}, - nums = Quiet @ ToExpression["{" <> str <> "}"]; - - If[MatchQ[nums, {__Integer}] && Length[nums] >= 2, - StringRiffle[ToString /@ sleepSort[nums], ", "], - $usage - ] -]; - -sleepSortMain[___] := $usage; - -Print /@ sleepSortMain /@ { - (* Valid cases *) - "4, 5, 3, 1, 2", - "4, 5, 3, 1, 4, 2", - "1, 2, 3, 4, 5", - "9, 8, 7, 6, 5, 4, 3, 2, 1", - - (* Invalid cases*) - "", - "1", - "4 5 3" -}; - -Print[sleepSortMain[]] \ No newline at end of file diff --git a/archive/p/pascal/sleep_sort.pas b/archive/p/pascal/sleep_sort.pas deleted file mode 100644 index 15c967120..000000000 --- a/archive/p/pascal/sleep_sort.pas +++ /dev/null @@ -1,124 +0,0 @@ -program SleepSort; - -{$mode objfpc}{$H+} - -uses - {$ifdef unix} - cthreads, - {$endif} - Classes, - Generics.Collections, - SysUtils, - syncobjs; - -type - TIntegerList = specialize TList; - -var - Results: TIntegerList; - Lock: TCriticalSection; - -type - TSleepSortThread = class(TThread) - private - FValue: integer; - protected - procedure Execute; override; - public - constructor Create(AValue: integer); - end; - -constructor TSleepSortThread.Create(AValue: integer); -begin - inherited Create(False); - FreeOnTerminate := False; - FValue := AValue; -end; - -procedure TSleepSortThread.Execute; -begin - Sleep(FValue * 10); - Lock.Acquire; - try - Results.Add(FValue); - finally - Lock.Release; - end; -end; - -procedure ShowUsage; -begin - Writeln('Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5"'); - Halt(1); -end; - -function ParseIntegerList(const S: string): TIntegerList; -var - Tokens: TStringArray; - Token: string; - Value: integer; -begin - if S.Trim = '' then - ShowUsage; - - Tokens := S.Split([',']); - if Length(Tokens) < 2 then - ShowUsage; - - Result := TIntegerList.Create; - for Token in Tokens do - begin - if not TryStrToInt(Trim(Token), Value) then - begin - Result.Free; - ShowUsage; - end; - Result.Add(Value); - end; -end; - -function FormatIntegerList(const List: TIntegerList): string; -var - i: integer; -begin - Result := ''; - for i := 0 to List.Count - 1 do - begin - if i > 0 then - Result += ', '; - Result += IntToStr(List[i]); - end; -end; - -var - Numbers: TIntegerList; - Threads: array of TSleepSortThread; - i: integer; -begin - if ParamCount <> 1 then - ShowUsage; - - Numbers := ParseIntegerList(ParamStr(1)); - Results := TIntegerList.Create; - Lock := TCriticalSection.Create; - - try - SetLength(Threads, Numbers.Count); - - for i := 0 to Numbers.Count - 1 do - Threads[i] := TSleepSortThread.Create(Numbers[i]); - - for i := 0 to High(Threads) do - begin - Threads[i].WaitFor; - Threads[i].Free; - end; - - Writeln(FormatIntegerList(Results)); - finally - Numbers.Free; - Results.Free; - Lock.Free; - end; -end. - diff --git a/archive/p/php/sleep-sort.php b/archive/p/php/sleep-sort.php deleted file mode 100644 index c0d0816bf..000000000 --- a/archive/p/php/sleep-sort.php +++ /dev/null @@ -1,110 +0,0 @@ - array( - 'decimal' => TRUE, - 'min_range' => PHP_INT_MIN, - 'max_range' => PHP_INT_MAX - ) - ) - ) === FALSE - ) - { - return FALSE; - } - - return intval($str_value); -} - -function parse_int_array($str_values) -{ - $str_array = explode(",", $str_values); - $values = array(); - foreach ($str_array as $str_value) - { - $value = parse_int($str_value); - if ($value === FALSE) - { - return FALSE; - } - - array_push($values, $value); - } - - return $values; -} - -// PHP requires PECL to be install to have threads. However, the docker -// image does not have this. Therefore, just monitor the clock and store -// values as each sleep time elapses -function sleep_sort($sleep_times) -{ - // Initialize values - $values = array(); - - // Wait for all sleep times are complete - $start = microtime(TRUE); - while (TRUE) - { - // For each sleep time that is not complete, when sleep time expires, append the - // sleep time to the list of values and remove the sleep time from the list - $elapsed_time = microtime(TRUE) - $start; - $new_sleep_times = array(); - foreach ($sleep_times as $sleep_time) - { - if ($elapsed_time >= $sleep_time) - { - array_push($values, $sleep_time); - } - else - { - array_push($new_sleep_times, $sleep_time); - } - } - - $sleep_times = $new_sleep_times; - if (count($sleep_times) < 1) - { - return $values; - } - - time_nanosleep(0, 500_000_000); - } -} - -// Exit if too few arguments -if (count($argv) < 2) -{ - usage(); -} - -// Parse 1st argument. Exit if invalid or too few values -$values = parse_int_array($argv[1]); -if ($values === FALSE || count($values) < 2) -{ - usage(); -} - -// Run sleep sort and show results -$values = sleep_sort($values); -printf("%s\n", implode(", ", $values)); diff --git a/archive/p/powershell/SleepSort.ps1 b/archive/p/powershell/SleepSort.ps1 deleted file mode 100644 index e763e9b3e..000000000 --- a/archive/p/powershell/SleepSort.ps1 +++ /dev/null @@ -1,31 +0,0 @@ -function Show-Usage() { - Write-Host 'Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5"' - Exit 1 -} - -function Parse-IntList([string]$Str) { - @($Str.Split(",") | ForEach-Object { [int]::Parse($_) }) -} - -function Invoke-SleepSort([int[]]$Values) { - @($Values | ForEach-Object -Parallel { - Start-Sleep $_ - $_ - } -ThrottleLimit $Values.Length) -} - -if ($args.Length -lt 1) { - Show-Usage -} - -try { - $values = Parse-IntList $args[0] - if ($values.Length -lt 2) { - Show-Usage - } -} catch { - Show-Usage -} - -$sortedValues = Invoke-SleepSort $values -Write-Host ($sortedValues -join ', ') diff --git a/archive/p/python/sleep_sort.py b/archive/p/python/sleep_sort.py deleted file mode 100644 index 698a9bfc1..000000000 --- a/archive/p/python/sleep_sort.py +++ /dev/null @@ -1,40 +0,0 @@ -import sys -import threading -from time import sleep - - -def arg_to_list(string): - return [int(x.strip(" "), 10) for x in string.split(',')] - - -def sleep_sort(i, output): - sleep(i) - output.append(i) - - -def error_and_exit(): - print('Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5"') - sys.exit() - - -def main(): - if len(sys.argv) == 1 or not sys.argv[1] or len(sys.argv[1].split(",")) == 1: - error_and_exit() - - array = arg_to_list(sys.argv[1]) - - threads = [] - output = [] - for i in array: - arg_tuple = (i, output) - thread = threading.Thread(target=sleep_sort, args=arg_tuple) - thread.start() - threads.append(thread) - - for thread in threads: - thread.join() - - print(output) - - -main() diff --git a/archive/r/rust/sleep-sort.rs b/archive/r/rust/sleep-sort.rs deleted file mode 100644 index 407ec0fbc..000000000 --- a/archive/r/rust/sleep-sort.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::env::args; -use std::process::exit; -use std::str::FromStr; -use std::thread; -use std::time::Duration; -use std::sync::{Arc, Mutex}; - -fn usage() -> ! { - println!("Usage: please provide a list of at least two integers to sort in the format \"1, 2, 3, 4, 5\""); - exit(0); -} - -fn parse_int(s: &str) -> Result::Err> { - s.trim().parse::() -} - -fn parse_int_list(s: &str) -> Result, ::Err> { - s.split(',') - .map(parse_int) - .collect::, ::Err>>() -} - -fn sleep_sort(arr: &mut Vec) { - // Start sleep threads that sleep for specified time and append that time to result - let mut threads = vec![]; - let result_mutex = Arc::new(Mutex::new(vec![])); - for sleep_time in arr.clone() { - let result_mutex_clone = Arc::clone(&result_mutex); - let value = sleep_time.clone(); - threads.push( - thread::spawn(move || { - thread::sleep(Duration::from_secs(value as u64)); - result_mutex_clone.lock().unwrap().push(value); - }) - ) - } - - // Wait for threads to finish - for thread in threads { - thread.join().unwrap(); - } - - // Store result - *arr = result_mutex.lock().unwrap().to_vec(); -} - -fn main() { - let mut args = args().skip(1); - - // Convert 1st command-line argument to list of integers - let mut arr: Vec = args - .next() - .and_then(|s| parse_int_list(&s).ok()) - .unwrap_or_else(|| usage()); - - // Exit if list too small - if arr.len() < 2 { - usage(); - } - - sleep_sort(&mut arr); - println!("{arr:?}"); -} diff --git a/archive/s/scala/SleepSort.scala b/archive/s/scala/SleepSort.scala deleted file mode 100644 index 12ca72dac..000000000 --- a/archive/s/scala/SleepSort.scala +++ /dev/null @@ -1,59 +0,0 @@ -import java.util.concurrent.{CountDownLatch, Executors} -import java.util.{ArrayList, Collections} -import scala.util.Try -import scala.jdk.CollectionConverters.* - -object SleepSort: - - def main(args: Array[String]): Unit = - args.toList match - case raw :: Nil => - val numbers = parse(raw) - if numbers.length < 2 then usage() - println(format(sleepSort(numbers))) - - case _ => - usage() - - private def usage(): Nothing = - println("""Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5"""") - sys.exit(1) - - private def parse(input: String): List[Int] = - input - .split(",") - .iterator - .map(_.trim) - .filter(_.nonEmpty) - .flatMap(s => Try(s.toInt).toOption) - .toList match - case Nil => usage() - case xs => xs - - private def format(xs: List[Int]): String = - xs.mkString(", ") - - private def sleepSort(input: List[Int]): List[Int] = - val sortedList = - Collections.synchronizedList(new ArrayList[Int]()) - - val executor = Executors.newCachedThreadPool() - val latch = new CountDownLatch(input.size) - - input.foreach { n => - executor.submit(() => - try - Thread.sleep(n.toLong * 100L) - sortedList.add(n) - catch - case _: InterruptedException => - Thread.currentThread().interrupt() - finally - latch.countDown() - ) - } - - latch.await() - executor.shutdown() - - sortedList.asScala.toList \ No newline at end of file diff --git a/archive/s/swift/sleep-sort.swift b/archive/s/swift/sleep-sort.swift deleted file mode 100644 index e181c997c..000000000 --- a/archive/s/swift/sleep-sort.swift +++ /dev/null @@ -1,59 +0,0 @@ -import Foundation - -let usage = """ - Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5" - """ - -extension StringProtocol { - var trimmed: String { trimmingCharacters(in: .whitespacesAndNewlines) } -} - -func parseIntegers(from args: [String]) -> [Int]? { - guard args.count == 2 else { return nil } - - let parts = args[1].split(separator: ",", omittingEmptySubsequences: false) - let values = parts.compactMap { Int($0.trimmed) } - - guard values.count == parts.count, - values.count >= 2 - else { - return nil - } - - return values -} - -func sleepSorted(_ numbers: [Int]) -> [Int] { - let group = DispatchGroup() - let lock = NSLock() - - var result: [Int] = [] - - let minValue = numbers.min() ?? 0 - let offset = minValue < 0 ? abs(minValue) : 0 - - for number in numbers { - group.enter() - - let delayMilliseconds = (number + offset) * 1000 - - DispatchQueue.global().asyncAfter(deadline: .now() + .milliseconds(delayMilliseconds)) { - lock.lock() - result.append(number) - lock.unlock() - - group.leave() - } - } - - group.wait() - return result -} - -guard let numbers = parseIntegers(from: CommandLine.arguments) else { - print(usage) - exit(1) -} - -let sorted = sleepSorted(numbers) -print(sorted.map(String.init).joined(separator: ", ")) diff --git a/archive/t/tcl/sleep-sort.tcl b/archive/t/tcl/sleep-sort.tcl deleted file mode 100644 index 84df8b3cf..000000000 --- a/archive/t/tcl/sleep-sort.tcl +++ /dev/null @@ -1,56 +0,0 @@ -package require Tcl 8.6 - -proc usage {} { - puts stderr {Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5"} - exit 1 -} - -proc parseList {s} { - set tokens [split [string trim $s] ","] - if {[llength $tokens] < 2} { usage } - - set result {} - - set result {} - foreach token $tokens { - set t [string trim $token] - if {$t eq "" || [catch {expr {int($t)}} val]} usage - lappend result $val - } - return $result -} - -proc isSorted {lst} { - set prev [lindex $lst 0] - foreach x [lrange $lst 1 end] { - if {$x < $prev} {return 0} - set prev $x - } - return 1 -} - -proc sleepSort {lst} { - set ::sortedList {} - set ::done 0 - - foreach num $lst { - after [expr {$num * 10}] [list lappend ::sortedList $num] - } - - set max [lindex $lst 0] - foreach n $lst {if {$n > $max} {set max $n}} - - after [expr {$max * 10 + 50}] {set ::done 1} - vwait ::done - - return $::sortedList -} - -proc formatList {lst} { return [join $lst ", "] } - -if {$argc != 1} { usage } - -set numbers [parseList [lindex $argv 0]] -set result [sleepSort $numbers] -puts [formatList $result] - diff --git a/archive/t/typescript/sleep-sort.ts b/archive/t/typescript/sleep-sort.ts deleted file mode 100644 index 15e421809..000000000 --- a/archive/t/typescript/sleep-sort.ts +++ /dev/null @@ -1,56 +0,0 @@ -function printUsage(): void { - console.log( - 'Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5"', - ); - process.exit(1); -} - -function sleepSort(arr: number[]): void { - const sorted: number[] = []; - - function sleepSortHelper(item: number): void { - setTimeout(() => { - sorted.push(item); - - if (sorted.length === arr.length) { - console.log(sorted.join(", ")); - } - }, item * 1000); - } - - arr.forEach((item) => { - if (item < 0) { - printUsage(); - } - sleepSortHelper(item); - }); -} - -function parseInput(input: string): number[] { - return input - .split(",") - .map((s) => s.trim()) - .map((s) => Number.parseInt(s, 10)); -} - -function isValid(arr: number[]): boolean { - return arr.length >= 2 && !arr.some((n) => Number.isNaN(n)); -} - -function main(): void { - const input = process.argv[2]; - - if (!input) { - printUsage(); - } - - const numbers = parseInput(input); - - if (!isValid(numbers)) { - printUsage(); - } - - sleepSort(numbers); -} - -main(); diff --git a/archive/v/visual-basic/sleep-sort.vb b/archive/v/visual-basic/sleep-sort.vb deleted file mode 100644 index 3c3a125f5..000000000 --- a/archive/v/visual-basic/sleep-sort.vb +++ /dev/null @@ -1,50 +0,0 @@ -Imports System.Collections.Concurrent - -Public Module SleepSort - - Private Sub ShowUsage() - Console.WriteLine("Usage: please provide a list of at least two integers to sort in the format ""1, 2, 3, 4, 5""") - Environment.Exit(1) - End Sub - - Public Sub Main(args As String()) - - If args.Length <> 1 Then - ShowUsage() - End If - - Try - Dim xs = args(0). - Split(","c, StringSplitOptions.RemoveEmptyEntries). - Select(Function(i) Integer.Parse(i.Trim())). - ToList() - - If xs.Count <= 1 Then - ShowUsage() - End If - - Dim sortedXs As New ConcurrentQueue(Of Integer) - Dim tasks As New List(Of Task) - - For Each x In xs - - Dim captured = x - - tasks.Add(Task.Run(Async Function() - Await Task.Delay(captured * 1000) - sortedXs.Enqueue(captured) - End Function)) - - Next - - Task.WaitAll(tasks.ToArray()) - - Console.WriteLine(String.Join(", ", sortedXs)) - - Catch - ShowUsage() - End Try - - End Sub - -End Module \ No newline at end of file diff --git a/needs-attention/archive/x/x86-64/sleep-sort.asm b/needs-attention/archive/x/x86-64/sleep-sort.asm deleted file mode 100644 index 8117906ac..000000000 --- a/needs-attention/archive/x/x86-64/sleep-sort.asm +++ /dev/null @@ -1,620 +0,0 @@ -%MACRO POPREGS 0 -POP R9 -POP R8 -POP R10 -POP RSI -POP RDI -POP RDX -POP RCX -POP RBX -POP RAX -%ENDMACRO -%MACRO PUSHREGS 0 -PUSH RAX -PUSH RBX -PUSH RCX -PUSH RDX -PUSH RDI -PUSH RSI -PUSH R10 -PUSH R8 -PUSH R9 -%ENDMACRO -%MACRO SLEEP 0 -MOV RAX, SYS_NANOWAIT -MOV RDI, timespec -MOV RSI, 0 -SYSCALL -%ENDMACRO - - -;I/O -%DEFINE SYS_WRITE 1 -%DEFINE STDOUT 1 - -;Signals -%DEFINE SYS_RT_SIGACTION 13 -%DEFINE SIGCHLD 17 -%DEFINE SIG_IGN 0x01 ;Ignore signal so we don't need to use a signal handler. -%DEFINE SIGSETSIZE 8 -;Flags -%DEFINE SA_NOCLDWAIT 0x02 ;Reap child processes automatically. - -;Memory -%DEFINE SYS_MMAP 9 -;PROTS (RDX) -%DEFINE PROT_READ 0x01 -%DEFINE PROT_WRITE 0x02 -;FLAGS (R10) -%DEFINE MAP_SHARED 0x01 -%DEFINE MAP_ANONYMOUS 0x20 - -%DEFINE SYS_MUNMAP 11 - -;Processes -%DEFINE SYS_NANOWAIT 35 -%DEFINE SYS_CLONE 56 -;Flags -%DEFINE CLONE_VM 0x0100 -%DEFINE CLONE_SIGHAND 0x0800 -%DEFINE CLONE_THREAD 0x00010000 -%DEFINE CLONE_SETTLS 0x00080000 - -%DEFINE SYS_EXIT 60 - -%DEFINE SYS_ARCH_PRCTL 158 -%DEFINE ARCH_SET_FS 0x1002 -%DEFINE ARCH_GET_FS 0x1003 - - -%DEFINE SYS_FUTEX 202 -%DEFINE FUTEX_WAIT 0 -%DEFINE FUTEX_WAKE 1 - - - -;_start function definitions -%DEFINE _start.STACK_INIT 32 -%DEFINE _start.argc 8 -%DEFINE _start.argv0 16 -%DEFINE _start.argv1 24 -; RBP+ ^ -; RBP- v -%DEFINE _start.SEMAPHORE 0 -%DEFINE _start.threadLock 8 -%DEFINE _start.threadLock.MUTEX 0 -%DEFINE _start.threadCount 16 - -;FSM function definitions -%DEFINE FSM.STACK_INIT 40 -%DEFINE FSM.threadValue 8 -%DEFINE FSM.numPtr 16 -%DEFINE FSM.numLen 24 -%DEFINE FSM.threadTLSPtr 32 - -%DEFINE threadTLS.size 56 ; Each -%DEFINE threadTLS.ptr 0 -%DEFINE threadTLS.timespec 8 -%DEFINE threadTLS.timespec.seconds 8 -%DEFINE threadTLS.timespec.nanoseconds 16 -%DEFINE threadTLS.numLen 24 -%DEFINE threadTLS.numPtr 32 -%DEFINE threadTLS.sleepTime 40 - -%DEFINE INT_MAX 2147483647 -%DEFINE THREAD_LIMIT 32 ;32 threads seems reasonable. - - -section .data - parentStackBase dq 0 ; I was trying to use R12 to hold the pointer to _start's RBP but I don't think a register should be squatted on for that long. RBP is a lot better because it's static inside the current function. - align 16, db 0 - MUTEX dq 0 - printMUTEX dq 0 - spawnMUTEX dq 0 - threadCount dq 0 - argc dq 0 - stringAddress dq 0 -section .rodata -errorMsg: - .txt db 'Usage: please provide a list of at least two integers to sort in the format "1, 2, 3, 4, 5"', 0xA - .len equ $- .txt - -main_sigAction: - .sa_handler dq SIG_IGN - .sa_mask times 128 db 0 - .sa_flags dd SA_NOCLDWAIT - .padding dd 0 - .sa_restorer dq 0 - -timespec: - %DEFINE timespec.seconds 0 - %DEFINE timespec.nanoseconds 8 - ;Placing this here so we know how the timespec struct is laid out in memory and to add delays so the container doesn't mess up our timings. - .seconds dq 0 - .nanoseconds dq 500 - - -commaSpace: - .txt db ', ' - .len equ $- .txt - -creation: - .txt db 'Thread Spawned',0xA - .len equ $- .txt - -section .text -; ---------------------------------------------------------------------------- -; Function: incThreadCount/decThreadCount/readThreadCount -; Description: -; Made to ensure atomicity of threadCount in .data across all threads and atomicity of its usage in all threads. -; A container for increasing/reading threadCount. -; Parameters: -; RDI - () Unused. -; RSI - () Unused. -; RDX - () Unused. -; R10 - () Unused. -; R8 - () Unused. -; R9 - () Unused. -; Returns: -; RAX - None for incThreadCount/decThreadCount, as RAX is just clobbered. threadCount value for readThreadCount as threadCount is stored in RAX. -; --------------------------------------------------------------------------- -incThreadCount: - LEA RAX, [threadCount] - LOCK INC QWORD [RAX] - MFENCE - RET -decThreadCount: - LEA RAX, [threadCount] - LOCK DEC QWORD [RAX] - MFENCE - RET -readThreadCount: - MFENCE - LEA RAX, [threadCount] - MOV RAX, QWORD [RAX] - LFENCE - RET -; ---------------------------------------------------------------------------- -; Function: initializeTLS -; Description: -; Initializes TLS for new thread. -; This function does not have a stack frame setup. -; TO ONLY BE CALLED FROM FSM. -; Parameters: -; RDI - (void*) Base ptr to parent stack frame. -; RSI - () Unused. -; RDX - () Unused. -; R10 - () Unused. -; R8 - () Unused. -; R9 - () Unused. -; Returns: -; RAX - TLS pointer. -; --------------------------------------------------------------------------- -initializeTLS: - PUSH RDI - MOV RAX, SYS_MMAP - MOV RDI, 0 ; No address hint. - MOV RSI, threadTLS.size ; Size of TLS buffer. - MOV RDX, PROT_READ | PROT_WRITE ; We can read and write to this section of memory. - MOV R10, MAP_SHARED | MAP_ANONYMOUS ; Share memory across processes and don't map to a file. - MOV R8, -1 ; No file descriptor. - MOV R9, 0 ; No offset. - SYSCALL - POP RDI - - MOV RSI, RDI ; RS(ource)I(ndex) will hold our source (Base ptr to stack frame) instead of RD(estination)I(ndex), where our destination register will hold the TLS pointer. - - MOV [RSI - FSM.threadTLSPtr], RAX - MOV RDI, RAX ; RDI will hold the pointer to our TLS for now. - MOV RDX, 0 ; RDX will hold the data to place into the TLS buffer. - MOV [RAX], RAX ; Move the pointer to the TLS into TLS[0]. I LOVE MOVs like these. - MOV RDX, [RSI - FSM.threadValue] - MOV [RDI + threadTLS.sleepTime], RDX - MOV [RDI + threadTLS.timespec.seconds], RDX - MOV RDX, [RSI - FSM.numLen] - MOV [RDI + threadTLS.numLen], RDX - MOV RDX, [RSI - FSM.numPtr] - MOV RDX, [RDX] - MOV [RDI + threadTLS.numPtr], RDX - MFENCE ; Allow all of these load and store operations to occur before any others afterwards do. - - MOV RAX, RDI - RET -; ---------------------------------------------------------------------------- -; Function: sleep_thread -; Description: -; The FSM function calls this when wanting to create a thread, then stays here if the child, or RETs back when the parent thread, then uses nanosleep to wait n seconds to print. -; FSM will unlock the FUTEX making the cloned threads sleep once all of the threads are created, synchronizing the nanosleep times. -; Printing is locked through a spinlock when a thread is printing its value to avoid printing "race conditions". Uses TLS through the FS segment to address variables related to the spawned thread. -; Afterwards, it cleans up its own memory and runs SYS_EXIT on itself. -; Parameters: -; RDI - (void*) Pointer to allocated TLS memory to set FS base to. -; RSI - () Unused. -; RDX - () Unused. -; R10 - () Unused. -; R8 - () Unused. -; R9 - () Unused. -; Returns: -; RAX - None. -; --------------------------------------------------------------------------- -sleep_thread: - PUSH RDI - - ;Spawn sleep thread. - MOV RAX, SYS_CLONE - MOV R10, RDI ; Move TLS pointer to R10. - MOV RDI, CLONE_VM | CLONE_SIGHAND | CLONE_SETTLS | CLONE_THREAD ; Share virtual memory with parent, share signal handlers, allow TLS to be set through the system call, and a new thread.. - MOV RSI, 0 ; No new stack. - MOV RDX, 0 ; No parent TID. - MOV R10, 0 ; No child TID. - MOV R8, 0 ; No child TLS ptr. - SYSCALL - - ; If RAX == 0, then it is the child thread, and we can continue here. If not, RET back to FSM as the thread is the parent thread. - CMP RAX, 0 - JZ .thread - ADD RSP, 8 ; Clear out stack frame for here. - RET - .thread: - POP RDI - MOV RAX, SYS_ARCH_PRCTL - MOV RDI, ARCH_SET_FS - MOV RSI, R13 - SYSCALL - ;We can now dereference items in the TLS through [FS:n] now. - CALL incThreadCount - ;Make thread wait on the lock at RBP[-_start.threadLock] in _start. - MOV RAX, SYS_FUTEX - MOV RDI, MUTEX - MOV RSI, FUTEX_WAIT - MOV RDX, _start.threadLock.MUTEX ; Wake up when the mutex location in RDI dereferences to zero (WAKE) - MOV R10, 0 ; No timeout. - MOV R8, 0 ; No requeue - MOV R9, 0 ; Unused for this. - SYSCALL - ;Sleep for n seconds. - MOV RAX, SYS_NANOWAIT - MOV RDI, [FS:threadTLS.ptr] - ADD RDI, threadTLS.timespec.seconds - MOV RSI, 0 ; We don't care about remaining time. - SYSCALL - ;Lock printing. - getPrintLock: - MOV R15, 1 - getPrintLockRetry: - XCHG R15, [printMUTEX] - TEST R15, R15 - JE printLockObtained - MOV RAX, SYS_FUTEX - MOV RDI, printMUTEX - MOV RSI, FUTEX_WAIT - MOV RDX, 0 ; Wake up when the memory location in RDI dereferences to zero (WAKE) - MOV R10, 0 ; No timeout. - MOV R8, 0 ; No requeue - MOV R9, 0 ; Unused for this. - SYSCALL - JMP getPrintLockRetry - printLockObtained: - ; Print number - MOV RAX, SYS_WRITE - MOV RDI, STDOUT - MOV RSI, [FS:0] - ADD RSI, threadTLS.numPtr ; Move pointer to numPtr in the TLS. - MOV RDX, [FS:threadTLS.numLen] - SYSCALL - - ; If not the last thread, print comma, then fall through to .kill, if it is the last thread, jump to .kill - CALL readThreadCount - CMP RAX, 1 - JE .kill - MOV RAX, SYS_WRITE - MOV RDI, STDOUT - MOV RSI, commaSpace.txt - MOV RDX, commaSpace.len - SYSCALL - .kill: - ;Unlock printing. - MOV R15, 0 - XCHG R15, [printMUTEX] - MOV RAX, SYS_FUTEX - MOV RDI, printMUTEX - MOV RSI, FUTEX_WAKE - MOV RDX, INT_MAX - MOV R10, 0 ; No timeout. - MOV R8, 0 ; No requeue. - MOV R9, 0 ; Unused. - SYSCALL - - MOV RAX, SYS_MUNMAP - MOV RDI, [FS:threadTLS.ptr] - MOV RSI, threadTLS.size - SYSCALL - - MOV RAX, [parentStackBase] - LOCK INC QWORD [RAX - _start.SEMAPHORE] - CALL decThreadCount - - MOV RAX, SYS_EXIT - POP RDI - SYSCALL - - - - -global stringToInt -stringToInt: -; ---------------------------------------------------------------------------- -; Function: stringToInt -; Description: -; Takes a pointer to an integer string (comma or null terminated), and returns the string as an integer. I chose 32 bit registers because I only want a 64 bit result; no high or low part. -; Parameters: -; RDI - (char*) String address. -; RSI - (char*) End string address. -; RDX - () Unused. -; R10 - () Unused. -; R8 - () Unused. -; R9 - () Unused. -; Returns: -; RAX - The integer string converted into an integer. -; ---------------------------------------------------------------------------- - MOV RAX, 0 ;AL will store the character, for multiplication operation. - MOV RBX, 1 ;EBX will store the multiplier. - MOV RCX, RSI ;RCX will be the counter. - DEC RCX - MOV R9, 0 ;R9 will be used to store the return number temporarily. - - .loop: - MOV AL, [RCX] - SUB AL, '0' - DEC RCX - IMUL RAX, RBX - IMUL RBX, 10 - ADD R9, RAX - CMP RCX, RDI - JL .done - JMP .loop - .done: - MOV RAX, R9 - RET - -global FSM -FSM: -; ---------------------------------------------------------------------------- -; Function: FSM -; Description: -; A finite state machine that iterates over argv[1]. Uses a jump table to dispatch the program to change the state, and/or run specialized tasks such as spawning threads. -; At the end, it turns on ALL of the created threads so they are synchronized, then spinlocks until they are done "sorting"; afterwards, the function returns a user-specified value in RAX. -; Parameters: -; RDI - () Unused. -; RSI - () Unused. -; RDX - () Unused. -; R10 - () Unused. -; R8 - () Unused. -; R9 - () Unused. -; Returns: -; RAX - Dynamic while programming for debugging purposes, could be thread count, could be the semaphore, anything. Right now: thread count. Useful for use with the INT3 instruction. -; ---------------------------------------------------------------------------- - PUSH RBP - MOV RBP, RSP - SUB RSP, FSM.STACK_INIT - MOV QWORD [RBP - FSM.threadValue], 0 ; The sleep time, based on the command line argument. - MOV QWORD [RBP - FSM.numPtr], 0 ; Pointer to the beginning of the number argument on the command line. - MOV QWORD [RBP - FSM.numLen], 0 ; Length of the number. - MOV QWORD [RBP - FSM.threadTLSPtr], 0 ; Pointer to the thread TLS. - - MOV RAX, 0 ; The accumulator register will hold any return value. - MOV RBX, [stringAddress] ; The base register will hold the starting address of the number - MOV RCX, 0 ; The counter register will hold the loop counter. - MOV RDX, 0 ; The data register will hold the character. - MOV RSI, [stringAddress] ; The source register will hold the parent stack base pointer argv[1] string to be dereferenced from. - MOV R13, 0 ; R13 will hold the TLS pointer temporarily for calling sleep_thread. - - ;Initial checking if argv[1] is empty or not. Check if argument == "", on top of not allowing any non-number argument. - MOV DL, [RSI+RCX] - CMP DL, '0' - JL .error - CMP DL, '9' - JA .error - LEA RBX, [RSI] ; Move beginning pointer to RBX. - MOV [RBP - FSM.numPtr], RBX ; Move beginning pointer to RBP - FSM.numPtr - - .loop: - JMP [.jmpTable + RDX*8] - .jmpTable: - dq .zero ; Jump to .zero label if DL is a null character (terminator). - times 31 dq .error - dq .space ;Jump to .space label if DL is a space character. - times 11 dq .error - dq .comma ; Jump to .comma label if DL is a comma character. - times 3 dq .error - times 10 dq .num ; Jump to .num label if DL is 0-9 - times 69 dq .error - .num: - INC RCX ; Increase counter by one. - INC QWORD [RBP - FSM.numLen] ; Increase number length by one. - MOV DL, [RSI+RCX] ; Move new character into DL. - CMP DL, ' ' - JE .error - JMP [.jmpTable +RDX*8] ; Jump back to the jump table. - .comma: - ;This will spawn the threads. - PUSHREGS - CALL readThreadCount - CMP RAX, THREAD_LIMIT - JE .cutComma - LOCK INC QWORD [argc] - POPREGS - PUSHREGS - MOV RDI, RBX - MOV RSI, [stringAddress] - LEA RSI, [RSI+RCX] - CALL stringToInt - MOV [RBP - FSM.threadValue], RAX - POPREGS - - PUSHREGS - MOV RDI, RBP - CALL initializeTLS - MOV R13, RAX - POPREGS - ; Clear out the stack - MOV QWORD [RBP - FSM.threadValue ], 0 ;The sleep time, based on the command line argument. - MOV QWORD [RBP - FSM.numPtr ], 0 ;Pointer to the beginning of the number argument on the command line. - MOV QWORD [RBP - FSM.numLen ], 0 ;Length of the number. - MOV QWORD [RBP - FSM.threadTLSPtr ], 0 ;Pointer to the thread TLS. - SFENCE ;Allow all of these store operations to occur before others can happen. - - ;Spawn child thread. - PUSHREGS - MOV RDI, R13 - CALL sleep_thread - SLEEP - POPREGS - ;FSM iteration - .cutComma: - INC RCX - MOV DL, [RSI+RCX] - JMP [.jmpTable +RDX*8] - - .space: - MOV QWORD [RBP - FSM.numLen], 0 ; Clear number length. - INC RCX ; Increase counter by one. - LEA RBX, [RSI+RCX] ; Load effective address of RSI + RCX (offset) as new beginning of number ptr. - MOV [RBP - FSM.numPtr], RBX - MOV DL, [RSI+RCX] ; Move new character into DL. - JMP [.jmpTable +RDX*8] ; Jump back to the jump table. - - .zero: - ;Making sure we don't have inputs like just "1". If there hasn't been a comma yet, then _start.threadCount will be zero. - CALL readThreadCount - CMP RAX, 0 - JE .error - ;This will signal the end of the finite state machine, add the last thread, signal the threads to wake up, and move the control flow to threadManagment. - ;This will spawn the threads. - PUSHREGS - CALL readThreadCount - CMP RAX, THREAD_LIMIT - JE .cutZero - POPREGS - PUSHREGS - LOCK INC QWORD [argc] - MOV RDI, RBX - MOV RSI, [stringAddress] - LEA RSI, [RSI+RCX] - CALL stringToInt - MOV [RBP - FSM.threadValue], RAX - POPREGS - - PUSHREGS - LEA RDI, [RBP] - CALL initializeTLS - MOV R13, RAX - POPREGS - ; Clear out the stack - MOV R14, [RBP - FSM.threadValue] ;For debugging. - MOV QWORD [RBP - FSM.threadValue ], 0 ;The sleep time, based on the command line argument. - MOV QWORD [RBP - FSM.numPtr ], 0 ;Pointer to the beginning of the number argument on the command line. - MOV QWORD [RBP - FSM.numLen ], 0 ;Length of the number. - MOV QWORD [RBP - FSM.threadTLSPtr ], 0 ;Pointer to the thread TLS. - SFENCE ;Allow all of these store operations to occur before others can happen. - - ;Spawn child thread. - PUSHREGS - MOV RDI, R13 - CALL sleep_thread - SLEEP - POPREGS - .cutZero: - ;Wait for all threads to finish setup. - .mainWait: - .mainLock: - MFENCE - CALL readThreadCount - CMP RAX, [argc] - JE .mainUnlock - PAUSE - JMP .mainLock - .mainUnlock: - ;Wake up threads: - MOV RAX, SYS_FUTEX - MOV RDI, MUTEX - MOV RSI, FUTEX_WAKE - MOV RDX, INT_MAX - MOV R10, 0 ; No timeout. - MOV R8, 0 ; No requeue. - MOV R9, 0 ; Unused. - SYSCALL - - JMP .threadManagement - - .error: - ADD RSP, FSM.STACK_INIT - MOV RSP, RBP - POP RBP - - JMP _start.failure - - .threadManagement: - .lock: - MFENCE ; Wait for all memory ops to finish. - CALL readThreadCount - CMP RAX, 0 - JE .unlock - PAUSE - JMP .lock - - .unlock: - ADD RSP, FSM.STACK_INIT - MOV RSP, RBP - POP RBP - - CALL readThreadCount - RET - - - - - -global _start -_start: - PUSH RBP - MOV RBP, RSP - - MOV [parentStackBase], RBP ;Save base pointer for later. RBP will be addressed though R12 ONLY when we are in another stack frame; we'll only address through RBP in main. - MOV RAX, [RBP+_start.argv1] ;MOV string pointer into RAX - MOV [stringAddress], RAX ;Save string pointer. - - SUB RSP, _start.STACK_INIT - MOV QWORD [RBP - _start.SEMAPHORE ], 0 ;Semaphore for when all of the threads are finished, and main can run once again; we'll just spinlock for main. - MOV QWORD [RBP - _start.threadLock ], _start.threadLock.MUTEX ;Lock so we can wait to start all threads. - MOV QWORD [RBP - _start.threadCount ], 0 ;Thread count. - - ;Allowing parent process to automatically reap children as they exit. - MOV RAX, SYS_RT_SIGACTION - MOV RDI, SIGCHLD - MOV RSI, main_sigAction - MOV RDX, 0 - MOV R10, 8 ; 8 bytes. - SYSCALL - - - CMP QWORD [RBP+_start.argc], 1 - JE .failure - CALL FSM - - MOV RAX, SYS_EXIT - XOR RDI, RDI - SYSCALL - - - - .failure: - MOV RAX, SYS_WRITE - MOV RDI, STDOUT - MOV RSI, errorMsg.txt - MOV RDX, errorMsg.len - SYSCALL - - MOV RAX, SYS_EXIT - XOR RDI, RDI - SYSCALL