Data update

This commit is contained in:
Ingy döt Net 2024-10-16 18:07:41 -07:00
parent 81fd053722
commit 52a6ef48dd
10248 changed files with 63654 additions and 6775 deletions

View file

@ -0,0 +1,193 @@
#include <algorithm>
#include <chrono>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <random>
#include <string>
#include <vector>
std::random_device random_device;
std::mt19937 generator(random_device());
int32_t measure_execution_time(const std::function<void(std::vector<int32_t>)>& sort, const std::vector<int32_t>& sequence) {
const auto start_time = std::chrono::high_resolution_clock::now();
sort(sequence);
const auto stop_time = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<std::chrono::microseconds>(stop_time - start_time).count();
}
std::vector<int32_t> ones(const int32_t& n) {
std::vector<int32_t> result(n, 1);
return result;
}
std::vector<int32_t> ascending(const int32_t& n) {
std::vector<int32_t> result(n);
std::iota(result.begin(), result.end(), 1);
return result;
}
std::vector<int32_t> random(const int32_t& n) {
std::vector<int32_t> result(n);
std::uniform_int_distribution<int32_t> distribution(1, 10 * n);
for ( int32_t i = 0; i < n; ++i ) {
result[i] = distribution(generator);
}
return result;
}
std::function<void(const std::vector<int32_t>&)> bubble_sort = [](std::vector<int32_t> vec) {
int32_t n = vec.size();
while ( n != 0 ) {
int32_t n2 = 0;
for ( int32_t i = 1; i < n; ++i ) {
if ( vec[i - 1] > vec[i] ) {
const int32_t temp = vec[i];
vec[i] = vec[i - 1];
vec[i - 1] = temp;
n2 = i;
}
}
n = n2;
}
};
std::function<void(const std::vector<int32_t>&)> insertion_sort = [](std::vector<int32_t> vec) {
for ( uint32_t index = 1; index < vec.size(); ++index ) {
const int32_t value = vec[index];
int32_t subIndex = index - 1;
while ( subIndex >= 0 && vec[subIndex] > value ) {
vec[subIndex + 1] = vec[subIndex];
subIndex -= 1;
}
vec[subIndex + 1] = value;
}
};
void quick_sort_recursive(std::vector<int32_t>& vec, const int32_t& first, const int32_t& last) {
if ( last - first < 1 ) {
return;
}
const int32_t pivot = vec[first + ( last - first ) / 2];
int32_t left = first;
int32_t right = last;
while ( left <= right ) {
while ( vec[left] < pivot ) {
left += 1;
}
while ( vec[right] > pivot ) {
right -= 1;
}
if ( left <= right ) {
const int32_t temp = vec[left];
vec[left] = vec[right];
vec[right] = temp;
left += 1;
right -= 1;
}
}
if ( first < right ) {
quick_sort_recursive(vec, first, right);
}
if ( left < last ) {
quick_sort_recursive(vec, left, last);
}
}
std::function<void(const std::vector<int32_t>&)> quick_sort = [](std::vector<int32_t> vec) {
quick_sort_recursive(vec, 0, vec.size() - 1);
};
void counting_sort(const std::vector<int32_t>& vec, const int32_t& exponent) {
const int32_t vec_size = vec.size();
std::vector<int32_t> output(vec_size, 0);
std::vector<int32_t> count(10, 0);
for ( int32_t i = 0; i < vec_size; ++i ) {
const int32_t t = ( vec[i] / exponent ) % 10;
count[t] += 1;
}
for ( int32_t i = 1; i <= 9; ++i ) {
count[i] += count[i - 1];
}
for ( int32_t i = vec_size - 1; i >= 0; --i ) {
const int32_t t = ( vec[i] / exponent ) % 10;
output[count[t] - 1] = vec[i];
count[t] -= 1;
}
}
std::function<void(const std::vector<int32_t>&)> radix_sort = [](std::vector<int32_t> vec) {
const int32_t min = *min_element(vec.begin(), vec.end());
if ( min < 0 ) { // If there are any negative numbers, make all the numbers positive
std::for_each(vec.begin(), vec.end(), [min](int32_t& n) { n -= min; });
}
const int32_t max = *std::max_element(vec.begin(), vec.end());
int32_t exponent = 1;
while ( max / exponent > 0 ) {
counting_sort(vec, exponent);
exponent *= 10;
}
if ( min < 0 ) { // If there were any negative numbers, return the array to its original values
std::for_each(vec.begin(), vec.end(), [min](int32_t& n) { n += min; });
}
};
std::function<void(const std::vector<int32_t>&)> shell_sort = [](std::vector<int32_t> vec) {
for ( int32_t gap : { 701, 301, 132, 57, 23, 10, 4, 1 } ) { // Marcin Ciura's gap sequence
for ( uint32_t i = gap; i < vec.size(); ++i ) {
const int32_t temp = vec[i];
int32_t j = i;
while ( j >= gap && vec[j - gap] > temp ) {
vec[j] = vec[j - gap];
j -= gap;
}
vec[j] = temp;
}
}
};
int main() {
const uint32_t repetitions = 10;
std::vector<uint32_t> lengths = { 1, 10, 100, 1'000, 10'000, 100'000 };
std::vector<std::function<void(const std::vector<int32_t>&)>> sorts =
{ bubble_sort, insertion_sort, quick_sort, radix_sort, shell_sort };
std::vector<std::string> sort_titles = { "Bubble", "Insert", "Quick ", "Radix ", "Shell " };
std::vector<std::string> sequence_titles = { "All Ones", "Ascending", "Random" };
std::vector<std::vector<std::vector<int64_t>>> totals =
{ 3, std::vector { sorts.size(), std::vector<int64_t>(lengths.size(), 0) } };
for ( uint32_t k = 0; k < lengths.size(); ++k ) {
const int32_t n = lengths[k];
std::vector<std::vector<int32_t>> sequences = { ones(n), ascending(n), random(n) };
for ( uint32_t repetition = 0; repetition < repetitions; ++repetition ) {
for ( uint32_t i = 0; i < sequences.size(); ++i ) {
for ( uint32_t j = 0; j < sorts.size(); ++j ) {
totals[i][j][k] += measure_execution_time(sorts[j], sequences[i]);
}
}
}
}
std::cout << "All timings in microseconds." << "\n\n";
std::cout << "Sequence length";
for ( const uint32_t& length : lengths ) {
std::cout << std::setw(10) << length;
}
std::cout << "\n\n";
for ( uint32_t i = 0; i < sequence_titles.size(); ++i ) {
std::cout << " " + sequence_titles[i] + ":" << "\n";
for ( uint32_t j = 0; j < sorts.size(); ++j ) {
std::cout << " " + sort_titles[j] + " ";
for ( uint32_t k = 0; k < lengths.size(); ++k ) {
const int64_t execution_time = totals[i][j][k] / repetitions;
std::cout << std::setw(10) << execution_time;
}
std::cout << "\n";
}
std::cout << "\n\n";
}
}

View file

@ -0,0 +1,192 @@
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public final class ComparingSortingAlgorithmsPerformance {
public static void main(String[] args) {
final int repetitions = 10;
List<Integer> lengths = List.of( 1, 10, 100, 1_000, 10_000, 100_000 );
List<Consumer<int[]>> sorts = List.of( bubbleSort, insertionSort, quickSort, radixSort, shellSort );
// Allow the JVM to compile the sort functions before timings start
for ( Consumer<int[]> sort : sorts ) {
sort.accept( new int[] { 1 } );
}
List<String> sortTitles = List.of( "Bubble", "Insert", "Quick ", "Radix ", "Shell " );
List<String> sequenceTitles = List.of( "All Ones", "Ascending", "Random" );
long[][][] totals = new long[sequenceTitles.size()][sorts.size()][lengths.size()];
for ( int k = 0; k < lengths.size(); k++ ) {
final int n = lengths.get(k);
List<int[]> sequences = List.of( ones.apply(n), ascending.apply(n), random.apply(n) );
for ( int repetition = 0; repetition < repetitions; repetition++ ) {
for ( int i = 0; i < sequences.size(); i++ ) {
for ( int j = 0; j < sorts.size(); j++ ) {
totals[i][j][k] += measureExecutionTime(sorts.get(j), sequences.get(i));
}
}
}
}
System.out.println("All timings in microseconds." + System.lineSeparator());
System.out.print("Sequence length");
for ( int length : lengths ) {
System.out.print(String.format("%8d ", length));
}
System.out.println(System.lineSeparator());
for ( int i = 0; i < sequenceTitles.size(); i++ ) {
System.out.println(" " + sequenceTitles.get(i) + ":");
for ( int j = 0; j < sorts.size(); j++ ) {
System.out.print(" " + sortTitles.get(j) + " ");
for ( int k = 0; k < lengths.size(); k++ ) {
final long executionTime = totals[i][j][k] / repetitions;
System.out.print(String.format("%8d ", executionTime));
}
System.out.println();
}
System.out.println(System.lineSeparator());
}
}
private static Consumer<int[]> bubbleSort = array -> {
int n = array.length;
while ( n != 0 ) {
int n2 = 0;
for ( int i = 1; i < n; i++ ) {
if ( array[i - 1] > array[i] ) {
final int temp = array[i];
array[i] = array[i - 1];
array[i - 1] = temp;
n2 = i;
}
}
n = n2;
}
};
private static Consumer<int[]> insertionSort = array -> {
for ( int index = 1; index < array.length; index++ ) {
final int value = array[index];
int subIndex = index - 1;
while ( subIndex >= 0 && array[subIndex] > value ) {
array[subIndex + 1] = array[subIndex];
subIndex -= 1;
}
array[subIndex + 1] = value;
}
};
private static Consumer<int[]> quickSort = array -> {
final class LocalClass {
private static void quickSortRecursive(int[] array, int first, int last) {
if ( last - first < 1 ) {
return;
}
final int pivot = array[first + ( last - first ) / 2];
int left = first;
int right = last;
while ( left <= right ) {
while ( array[left] < pivot ) {
left += 1;
}
while ( array[right] > pivot ) {
right -= 1;
}
if ( left <= right ) {
final int temp = array[left];
array[left] = array[right];
array[right] = temp;
left += 1;
right -= 1;
}
}
if ( first < right ) {
quickSortRecursive(array, first, right);
}
if ( left < last ) {
quickSortRecursive(array, left, last);
}
}
}
LocalClass.quickSortRecursive(array, 0, array.length - 1);
};
private static Consumer<int[]> radixSort = array -> {
final class LocalClass {
private static void countingSort(int[] array, int exponent) {
final int n = array.length;
int[] output = new int[n];
int[] count = new int[10];
for ( int i = 0; i < n; i++ ) {
final int t = ( array[i] / exponent ) % 10;
count[t] += 1;
}
for ( int i = 1; i <= 9; i++ ) {
count[i] += count[i - 1];
}
for ( int i = n - 1; i >= 0; i-- ) {
final int t = ( array[i] / exponent ) % 10;
output[count[t] - 1] = array[i];
count[t] -= 1;
}
for ( int i = 0; i < n; i++ ) {
array[i] = output[i];
}
}
}
final int min = Arrays.stream(array).min().getAsInt();
if ( min < 0 ) { // If there are any negative numbers, make all the numbers positive
array = Arrays.stream(array).map( i -> i - min).toArray();
}
final int max = Arrays.stream(array).max().getAsInt();
int exponent = 1;
while ( max / exponent > 0 ) {
LocalClass.countingSort(array, exponent);
exponent *= 10;
}
if ( min < 0 ) { // If there were any negative numbers, return the array to its original values
array = Arrays.stream(array).map( i -> i + min).toArray();
}
};
private static Consumer<int[]> shellSort = array -> {
for ( int gap : new int[] { 701, 301, 132, 57, 23, 10, 4, 1 } ) { // Marcin Ciura's gap sequence
for ( int i = gap; i < array.length; i++ ) {
final int temp = array[i];
int j = i;
while ( j >= gap && array[j - gap] > temp ) {
array[j] = array[j - gap];
j -= gap;
}
array[j] = temp;
}
}
};
private static Function<Integer, int[]> ones =
n -> Stream.generate( () -> 1 ).limit(n).mapToInt(Integer::valueOf).toArray();
private static Function<Integer, int[]> ascending = n -> IntStream.rangeClosed(1, n).toArray();
private static Function<Integer, int[]> random = n -> new Random().ints(1, 10 * n).limit(n).toArray();
private static long measureExecutionTime(Consumer<int[]> sort, int[] sequence) {
final long startTime = System.nanoTime();
sort.accept(sequence);
return ( System.nanoTime() - startTime ) / 1_000; // microseconds
}
}

View file

@ -0,0 +1,87 @@
# 20241006 Perl programming solution
use strict;
use warnings;
use Time::HiRes qw(time);
my ($rounds, $size) = (3, 2000);
my @allones = (1) x $size;
my @sequential = (1 .. $size);
my @randomized = map { $sequential[rand @sequential] } 1 .. $size;
sub insertion_sort {
my @a = @_;
for my $k (1 .. $#a) {
my ($j, $value) = ($k - 1, $a[$k]);
while ($j >= 0 && $a[$j] > $value) {
$a[$j + 1] = $a[$j];
$j--;
}
$a[$j + 1] = $value;
}
return @a;
}
sub merge_sort {
my @a = @_;
return @a if @a <= 1;
my $m = int(@a / 2);
my @l = merge_sort(@a[0 .. $m - 1]);
my @r = merge_sort(@a[$m .. $#a]);
return (@l, @r) if $l[-1] <= $r[0];
my @result;
while (@l && @r) {
push @result, $l[0] <= $r[0] ? shift @l : shift @r;
}
push @result, @l, @r;
return @result;
}
sub quick_sort {
my @data = @_;
return @data if @data <= 1;
my $pivot_index = int(rand(@data));
my $pivot = $data[$pivot_index];
@data = grep { $_ != $pivot } @data;
my (@left, @right);
foreach my $x (@data) {
$x < $pivot ? push @left, $x : push @right, $x;
}
return (quick_sort(@left), $pivot, quick_sort(@right));
}
sub comparesorts {
my ($rounds, @tosort) = @_;
my ($iavg, $mavg, $qavg);
foreach my $sort_type (('i', 'm', 'q') x $rounds) {
my @data_copy = @tosort;
my $t = time;
if ($sort_type eq 'i') {
insertion_sort(@data_copy);
$iavg += time - $t;
} elsif ($sort_type eq 'm') {
merge_sort(@data_copy);
$mavg += time - $t;
} elsif ($sort_type eq 'q') {
quick_sort(@data_copy);
$qavg += time - $t;
}
}
return ($iavg / $rounds, $mavg / $rounds, $qavg / $rounds);
}
foreach my $test (['ones', @allones], ['presorted', @sequential], ['randomized', @randomized]) {
my ($t, @d) = @$test;
print "Average sort times for $size $t:\n";
my ($i_time, $m_time, $q_time) = comparesorts($rounds, @d);
printf "insertion sort %0.9f\n", $i_time;
printf "merge sort %0.9f\n", $m_time;
printf "quick sort %0.9f\n", $q_time;
}