I have to write a command line that take two numbers in two different custom base and output in a third one.
By custom base, I mean that I have things like that:
- Input base 1: "!?\
- Input base 2: ajedpoi
- Output: rAfeB oiX
So starting from that I guess that bc
doesn't help, right?
Is there such a command or should I write some custom script? Could you give me some clues? I'm completly lost.
EDIT: the exercice exact instructions are:
Write a command line that takes numbers from variables FT_NBR1, in ’"?! base, and FT_NBR2, in mrdoc base, and displays the sum of both in gtaio luSnemf base.
In a way that with the following values:
FT_NBR1=\'?"\"'\
FT_NBR2=rcrdmddd
I would get the following output:
Salut
CodePudding user response:
How would one convert the string 789
into a number?
Well, 789 is equal to
7 × 102 8 × 101 9 × 100
But we're writing a program and we'll want to take advantage of looping.
( ( 7 ) × 10 8 ) × 10 9
Better yet,
( ( ( 0 ) × 10 7 ) × 10 8 ) × 10 9
We don't start with digits 7
, 8
and 9
, but their string representation.
(
(
(
0
) × 10 [ offset of "7" in "0123456789" ]
) × 10 [ offset of "8" in "0123456789" ]
) × 10 [ offset of "9" in "0123456789" ]
And finally, let's remove the last bit of reliance on base 10.
(
(
(
0
) × [ number of symbols in "0123456789" ] [ offset of "7" in "0123456789" ]
) × [ number of symbols in "0123456789" ] [ offset of "8" in "0123456789" ]
) × [ number of symbols in "0123456789" ] [ offset of "9" in "0123456789" ]
So the code would look like this:
- Set
n
to 0. - Set
base
to the number of symbols in the base. - For each digit,
- Set
n
to the result of the multiplication ofn
andbase
. - Get the offset of the digit in the array of symbols that make up the base.
- Set
n
to the result of the addition ofn
and the offset.
- Set
Example Perl implementation:
my @syms = split //, "01234567890";
my %sym_offset = map { $syms[$_] => $_ } 0 .. $#syms;
my $s = "...";
my $n = 0;
for my $sym ( split //, $s ) {
my $offset = $sym_offset{ $sym };
$n = $n * @syms $offset;
}
$s = $syms[ 0 ] if !length( $s );
say $n;
The opposite of this process can be taken to take a number and convert it to base. Instead of repeatedly multiplying, one would repeatedly divide, using the remainder as an index into the list of symbols that make up the base.
- Set
base
to the number of symbols in the base. - Set
s
to an empty string. - While
n
is greater than zero,- Find the remainder of
n
divided bybase
. - Get the symbol found at the offset equal to the remainder.
- Prepend the symbol to
s
. - Set
n
to the result of the subtraction of the remainder fromn
. - Set
n
to the result of the division ofn
bybase
.
- Find the remainder of
- If
s
is an empty string,- Set
s
to the first symbol.
- Set
Example Perl implementation:
my @syms = split //, "01234567890";
my %sym_offset = map { $syms[$_] => $_ } 0 .. $#syms;
my $n = ...;
my $s = "";
while ( $n ) {
my $offset = $n % @syms;
$s = $syms[ $offset ] . $s;
$n = ( $n - $offset ) / @syms;
}
say $n;
CodePudding user response:
Well, I was'nt clever enough. I can do it with just tr
and bc
I use tr
to convert from and back the weird "bases" and bc
with normal numbers.
Here's what I have done:
#!/bin/sh
NUM1=$(echo "$FT_NBR1" | tr \'\\\\\"\?\! '01234')
NUM2=$(echo "$FT_NBR2" | tr mrdoc '01234')
RES=$(echo "obase=13; ibase=5; $NUM1 $NUM2" | bc)
echo $RES | tr '0123456789abc' 'gtaio luSnemf'