#!/usr/bin/env perl

use strict;
use warnings;
use Math::Trig qw(pi);
sub insert (+$);
sub number2str ($;$);

my ( @values, @distances );

# generate A scale values and distances according to what is present on
# a Pickett Model N 3P-ES pocket slide rule, though half-tick resolution
# has been used, or double the number of values than actually present,
# given that a human can guess when something is 9.1 despite there only
# being ticks at 9 and 9.2
my $pad_by = 2;

# 1..3 at 20 ticks per digit, etc.
genvd( 1, 3,  20 );
genvd( 3, 6,  10 );
genvd( 6, 10, 5 );
# and similar pattern for next decade
genvd( 10, 30,  20 );
genvd( 30, 60,  10 );
genvd( 60, 100, 5 );

push @values,    number2str 100;
push @distances, log 100;

# pi is indicated on the scale
my $value = pi;
insert @distances, log $value;
insert @values, number2str $value, 8;

use Data::Dumper::Concise;
print Dumper { value => \@values, dist => \@distances };

write_out( 'a-distances', \@distances );
write_out( 'a-values',    \@values );

sub genvd {
    my ( $min, $max, $precision ) = @_;

    my $ticks = $precision * ( $max - $min ) * $pad_by;
    my $slope = ( $max - $min ) / $ticks;
    for my $v ( 0 .. $ticks - 1 ) {
        my $value = $slope * $v + $min;
        push @distances, log $value;
        push @values,    number2str $value;
    }
}

sub insert (+$) {
    for my $i ( 0 .. $#{ $_[0] } ) {
        if ( $_[0]->[$i] > $_[1] ) {
            splice @{ $_[0] }, $i, 0, $_[1];
            return;
        }
    }
    push @{ $_[0] }, $_[1];
}

sub number2str ($;$) {
    my $number    = shift;
    my $precision = shift // 3;
    my $str       = sprintf "%0${precision}f", $number;
    $str =~ s/(?<!\.)0+$//;
    return $str;
}

sub write_out {
    my ( $file, $ref ) = @_;
    open my $fh, '>', $file or die "could not write '$file': $!\n";
    for my $x (@$ref) {
        say $fh $x;
    }
}
