why passing the return value of an asNumber'ed string breaks io? - iolanguage

I just started the matasano security challenge, and thought about learning IO at the same time.
So now, i'm stuck on challenge 1 where I need to convert a string to base64.
Anyway i've come to the point where i need to convert from binary to decimal, here is my aproach:
binToDec := method( bin, <-- program does not enter this method
dec := 0
rem := 0
i := 0
while ( bin != 0,
rem = bin % 10
bin = bin / 10
dec = dec + rem * 2 pow( i )
i = i + 1
)
return dec
)
toBase64Ascii := method( slice,
tmp := ""
for( a, 0, slice size, <-- construct a string to use with asNumber
tmp = tmp .. slice at( a )
)
dec := binToDec( tmp asNumber ) <-- the line that make the whole thing crash
)
for ( a, 0, bin size, 6,
tmp := toBase64Ascii( bin slice( a, a + 6 )
***some more code***
)
there is no error message or anything, the program just hangs indefinitely.
From the documentation:
asNumber
Returns the receiver converted to a number. Initial whitespace is ignored.
So i must say i'm quite confused here, what is happening ?
I would have done some more research but io is imposible to google for...

I'm not sure what the expected input and output of your binToDec method is, but
while ( bin != 0,
rem = bin % 10
bin = bin / 10
dec = dec + rem * 2 pow( i )
i = i + 1
)
is likely an infinite loop. bin is a floating point number which is repeatedly divided by 10, which does not mean that it ever reaches 0.
I need to convert a string to base64.
Notice that there are asBase64 and fromBase64 methods on sequences.

Related

Is there a simple (possibly obfuscated) math expression for the number of days in a given month?

For use in cases where a standard library is not available. Assume that the month is given as an unsigned integer.
I'd be interested in seeing the shortest arithmetic expression that gives the correct answer, allowing or disallowing bitwise operators & masks but not lookup tables. Partial expressions can be saved into a variable for readability to showcase the idea used.
Here's an approach that uses only four simple arithmetic and bitwise ops and a 26-bit constant:
int days_in_month(unsigned m) {
// 121110 9 8 7 6 5 4 3 2 1 0
return 28 + ((0b11101110111110111011001100u >> m * 2u) & 0b11);
}
If you also want to handle leap year (no mention of it in the question), you can take a similar approach, at the cost of a few more operations and a 50-bit constant:
int days_in_month2(unsigned m, bool ly) {
return 28 + ((0b11101110111110111011011111101110111110111011001100u >> (m + 12*ly) * 2u) & 0b11);
}
If you are willing the pass the leap year in a different way, e.g., setting a bit like month | 16 to indicate leap year, it would be more efficient.
I assume you pass the month as 1 to 12, not 0 to 11.
Tests and generated asm can be seen on godbolt.
Variation om #BeeOnRope nice answer.
#include <stdbool.h>
int DaysPerMonth(int Month, bool IsLeapYear) {
assert(Month >= 1 && Month <= 12);
// 0b11101110111110111011001100u
// 3 B B E E C C
return (((0x3BBEECCu | (IsLeapYear << 2*2)) >> Month*2) & 3) + 28;
}
#include <stdio.h>
int main() {
for (int ly = 0; ly <= 1; ly++) {
for (int m = 1; m <= 12; m++) {
printf("(%2d %2d), ", m, DaysPerMonth(m,ly));
}
puts("");
}
return 0;
}
Brute force answer in pseudocode for readability:
monthlength(month,is_leapyear) :=
oddmonth = ( month + (month >= 8) ? 1 : 0) % 2 // Or (month ^ (month >> 3))&1
feb_days_offset = (month == 2) ? 2 - is_leapyear : 0
return 30 + oddmonth - feb_days_offset
Where month >= 8 can also be implemented with a bitshift since it's just the fourth bit in an unsigned representation, so that oddmonth is (first bit) xor (fourth bit), which can be consisely written as (month ^ (month >> 3))&1 . Similarly, subtracting the feb offset can be thought of as flipping the second bit on febuary, and flipping the first bit during leap year february.
single line with no intermediate variables:
monthlength(month,isleapyear) := 30 + ( month + (month >= 8 ? 1 : 0)) % 2 - (month==2 ? (2 - isleapyear) : 0)
Alternatively, one that uses exclusively bitwise arithmetic and shifts using the tricks discussed above:
monthlength(month,leapyear) := 30 ^ (month==2)<<1 ^ (month==2)&leapyear ^ (month^month>>3)&1
unsigned int m, leapyr, y ;
//m = month range is 1 to 12
//y = year range is 00 to 99
leapyr = ( ( y & 0x03 ) && 1 ); //0 means leap year and 1 means Non leap year
m = 30 + ( ( m & 1 ) ^ ( 1 && ( m & 8 ) ) ) - ( ( !( m & 13 ) ) ) - ( ( !( m & 13 ) ) & leapyr );
My answer is considering year. If you don't want to use assign leapyr variable 0 or 1 as you wish.

How to isolate leftmost bytes in integer

This has to be done in Perl:
I have integers on the order of e.g. 30_146_890_129 and 17_181_116_691 and 21_478_705_663.
These are supposedly made up of 6 bytes, where:
bytes 0-1 : value a
bytes 2-3 : value b
bytes 4-5 : value c
I want to isolate what value a is. How can I do this in Perl?
I've tried using the >> operator:
perl -e '$a = 330971351478 >> 16; print "$a\n";'
5050222
perl -e '$a = 17181116691 >> 16; print "$a\n";'
262163
But these numbers are not on the order of what I am expecting, more like 0-1000.
Bonus if I can also get values b and c but I don't really need those.
Thanks!
number >> 16 returns number shifted by 16 bit and not the shifted bits as you seem to assume. To get the last 16 bit you might for example use number % 2**16 or number & 0xffff. To get to b and c you can just shift before getting the last 16 bits, i.e.
$a = $number & 0xffff;
$b = ($number >> 16) & 0xffff;
$c = ($number >> 32) & 0xffff;
If you have 6 bytes, you don't need to convert them to a number first. You can use one the following depending on the order of the bytes: (Uppercase represents the most significant byte.)
my ($num_c, $num_b, $num_a) = unpack('nnn', "\xCC\xcc\xBB\xbb\xAA\xaa");
my ($num_a, $num_b, $num_c) = unpack('nnn', "\xAA\xaa\xBB\xbb\xAA\xaa");
my ($num_c, $num_b, $num_a) = unpack('vvv', "\xcc\xCC\xbb\xBB\xaa\xAA");
my ($num_a, $num_b, $num_c) = unpack('vvv', "\xaa\xAA\xbb\xBB\xcc\xCC");
If you are indeed provided with a number 0xCCccBBbbAAaa), you can convert it to bytes then extract the numbers you want from it as follows:
my ($num_c, $num_b, $num_a) = unpack('xxnnn', pack('Q>', $num));
Alternatively, you could also use an arithmetic approach like you attempted.
my $num_a = $num & 0xFFFF;
my $num_b = ( $num >> 16 ) & 0xFFFF;
my $num_c = $num >> 32;
While the previous two solutions required a Perl built to use 64-bit integers, the following will work with any build of Perl:
my $num_a = $num % 2**16;
my $num_b = ( $num / 2**16 ) % 2**16;
my $num_c = int( $num / 2**32 );
Let's look at ( $num >> 16 ) & 0xFFFF in detail.
Original number: 0x0000CCccBBbbAAaa
After shifting: 0x00000000CCccBBbb
After masking: 0x000000000000BBbb

Palindrome Number: what is wrong with my code?

I am writing code in c++ to detect if an input number is a Palindrome Number, which means its reverse is the same as the origin. I have problems computing the reverse int.
e.g.
121 returns true;
123 returns false;
12321 returns true;
10 returns false;
I input 123 and the sum should be 321. However, my code keeps returning 386. I stepped into the function with xcode. Still, I have no idea why reverse += (3 * 10) + 2 turns to be 35 or why the final reverse number to be 386.
int origin = x;
int reverse = 0;
while (x != 0) {
int digit = x % 10;
reverse += ((reverse * 10) + digit);
x /= 10;
}
why reverse += (3 * 10) + 2 turns to be 35
Because += adds what is on the right to the existing value of what’s on the left. (3 * 10) + 2 is 32, but reverse was already 3 and so you are adding your 32 to the existing 3, which is 35.
You don’t want to add to the value of reverse; you want to replace it.
Change
reverse += ((reverse * 10) + digit)
To
reverse = ((reverse * 10) + digit)

Cryptic TypeError: 'decimal.Decimal' object cannot be interpreted as an integer

I am struggling to understand why this function apparently fails in the Jupyter Notebook, but not in the IPython shell:
def present_value( r, n, fv = None, pmt = None ):
'''
Function to compute the Present Value based on interest rate and
a given future value.
Arguments accepted
------------------
* r = interest rate,
which should be given in its original percentage, eg.
5% instead of 0.05
* n = number of periods for which the cash flow,
either as annuity or single flow from one present value
* fv = future value in dollars,
if problem is annuity based, leave this empty
* pmt = each annuity payment in dollars,
if problem is single cash flow based, leave this empty
'''
original_args = [r, n, fv, pmt]
dec_args = [Decimal( arg ) if arg != None
else arg
for arg in original_args
]
if dec_args[3] == None:
return dec_args[2] / ( ( 1 + ( dec_args[0] / 100 ) )**dec_args[1] )
elif dec_args[2] == None:
# annuity_length = range( 1, dec_args[1] + 1 )
# Not allowed to add a Decimal object
# with an integer and to use it
# in the range() function,
# so we dereference the integer from original_args
annuity_length = range( 1, original_args[1] + 1 )
# Apply discounting to each annuity payment made
# according to number of years left till end
all_compounded_pmt = [dec_args[3] * ( 1 / ( ( 1 + dec_args[0] / 100 ) ** time_left ) ) \
for time_left in annuity_length
]
return sum( all_compounded_pmt )
When I imported the module that this function resides in, named functions.py, using from functions import *, and then executed present_value(r=7, n=35, pmt = 11000), I got the error:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-93-c1cc587f7e27> in <module>()
----> 1 present_value(r=7, n=35, pmt = 11000)
/path_to_file/functions.py in present_value(r, n, fv, pmt)
73 if dec_args[3] == None:
74 return dec_args[2]/((1 + (dec_args[0]/100))**dec_args[1])
---> 75
76 elif dec_args[2] == None:
77 # annuity_length = range(1, dec_args[1]+1)
TypeError: 'decimal.Decimal' object cannot be interpreted as an integer
but in the IPython shell, evaluating this function it works perfectly fine:
In [42]: functions.present_value(r=7, n=35, pmt = 11000)
Out[42]: Decimal('142424.39530474029537')
Can anyone please help me with this really confusing and obscure issue?

Perl function for negative integers using the 2's complement

I am trying to convert AD maxpwdAge (a 64-bit integer) into a number of days.
According to Microsoft:
Uses the IADs interface's Get method to retrieve the value of the domain's maxPwdAge attribute (line 5).
Notice we use the Set keyword in VBScript to initialize the variable named objMaxPwdAge—the variable used to store the value returned by Get. Why is that?
When you fetch a 64-bit large integer, ADSI does not return one giant scalar value. Instead, ADSI automatically returns an IADsLargeInteger object. You use the IADsLargeInteger interface's HighPart and LowPart properties to calculate the large integer's value. As you may have guessed, HighPart gets the high order 32 bits, and LowPart gets the low order 32 bits. You use the following formula to convert HighPart and LowPart to the large integer's value.
The existing code in VBScript from the same page:
Const ONE_HUNDRED_NANOSECOND = .000000100 ' .000000100 is equal to 10^-7
Const SECONDS_IN_DAY = 86400
Set objDomain = GetObject("LDAP://DC=fabrikam,DC=com") ' LINE 4
Set objMaxPwdAge = objDomain.Get("maxPwdAge") ' LINE 5
If objMaxPwdAge.LowPart = 0 Then
WScript.Echo "The Maximum Password Age is set to 0 in the " & _
"domain. Therefore, the password does not expire."
WScript.Quit
Else
dblMaxPwdNano = Abs(objMaxPwdAge.HighPart * 2^32 + objMaxPwdAge.LowPart)
dblMaxPwdSecs = dblMaxPwdNano * ONE_HUNDRED_NANOSECOND ' LINE 13
dblMaxPwdDays = Int(dblMaxPwdSecs / SECONDS_IN_DAY) ' LINE 14
WScript.Echo "Maximum password age: " & dblMaxPwdDays & " days"
End If
How can I do this in Perl?
Endianness may come into this, but you may be able to say
#!/usr/bin/perl
use strict;
use warnings;
my $num = -37_108_517_437_440;
my $binary = sprintf "%064b", $num;
my ($high, $low) = $binary =~ /(.{32})(.{32})/;
$high = oct "0b$high";
$low = oct "0b$low";
my $together = unpack "q", pack "LL", $low, $high;
print "num $num, low $low, high $high, together $together\n";
Am I missing something? As far as I can tell from your question, your problem has nothing at all to do with 2’s complement. As far as I can tell, all you need/want to do is
use Math::BigInt;
use constant MAXPWDAGE_UNIT_PER_SEC => (
1000 # milliseconds
* 1000 # microseconds
* 10 # 100 nanoseconds
);
use constant SECS_PER_DAY => (
24 # hours
* 60 # minutes
* 60 # seconds
);
my $maxpwdage_full = ( Math::BigInt->new( $maxpwdage_highpart ) << 32 ) + $maxpwdage_lowpart;
my $days = $maxpwdage_full / MAXPWDAGE_UNIT_PER_SEC / SECS_PER_DAY;
Note that I deliberately use 2 separate constants, and I divide by them in sequence, because that keeps the divisors smaller than the range of a 32-bit integer. If you want to write this another way and you want it to work correctly on 32-bit perls, you’ll have to keep all the precision issues in mind.