extracting binary data out of 8-bit byte and converting it to primitive types [C++] - c++

I have a vector of integers vector<int> that has 48 items in it. I want to extract binary data out of this(not sure if this is correct way to call it please edit it if it's wrong) i.e. a sequence of one or more bits and then convert them to a primitive type like int. I have come up with this solution:
int extractValue(vector<int> v, int startBit, int endBit) {
int beginByteIndex = (startBit / 8);
int endByteIndex = (endBit / 8);
vector<bool> bits;
bits.clear();
int startIndex = startBit % 8;
int endIndex = endBit % 8;
int value = v[beginByteIndex];
value = (value << startIndex);
int temp = 8;
if (beginByteIndex == endByteIndex) {
temp = endIndex + 1;
}
for (int i = startIndex; i < temp; i++) {
int temp = 0x80 & value;
bits.push_back(temp);
value <<= 1;
}
for (int i = beginByteIndex + 1; i < endByteIndex; i++) {
value = v[i];
for (int j = 0; j < 8; j++) {
int temp = 0x80 & value;
bits.push_back(temp);
value <<= 1;
}
}
if (endByteIndex > beginByteIndex) {
value = v[endByteIndex];
for (int i = 0; i <= endIndex; i++) {
int temp = 0x80 & value;
bits.push_back(temp);
value <<= 1;
}
}
int size = bits.size();
int p = 1;
int result = 0;
for (int i = size - 1; i >= 0; i--) {
result += (bits[i] * p);
p *= 2;
}
return result;
}
but this function is long, difficult to read and is done in C style. could someone please suggest a C++ way of doing this. I'm almost certain that C++ has a good, short and elegant way of doing this. also please edit the question so others with similar problem can benefit from it. Unfortunately My English is not that good to express it in a more general way.
EDIT:
as requested in comments for example I want to extract following information with following positions and length:
int year = extractValue(data, 0, 6);
int month = extractValue(data, 7, 10);
int day = extractValue(data, 11, 15);

a simple solution:
convert each byte to hex string (ostringstream or even sprintf can help), you got 2 digits, range is 0 to F.
for each hex digit you can create the bitmap like this:
0 = 0000,
1 = 0001,
2 = 0010,
...,
F = 1111,
add bits to the vector according to the bitmap
to recover - you take 4 bits and translate it back to digit, then take 2 digits and convert back to byte (say by adding 0x to the hex, isringstream to byte).

Related

Wrong output in Project Euler [duplicate]

I'm working on project euler problem number eight, in which ive been supplied this ridiculously large number:
7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
and am supposed to "Find the thirteen adjacent digits in the 1000-digit number that have the greatest product." EG the product of the first four adjacent digits is 7 * 3 * 1 * 6.
My code is the following:
int main()
{
string num = /* ridiculously large number omitted */;
int greatestProduct = 0;
int product;
for (int i=0; i < num.length() -12; i++)
{
product = ((int) num[i] - 48);
for (int j=i+1; j<i+13; j++)
{
product = product * ((int) num[j] - 48);
if (greatestProduct <= product)
{
greatestProduct = product;
}
}
}
cout << greatestProduct << endl;
}
I keep getting 2091059712 as the answer which project euler informs me is wrong and I suspect its too large anyway. Any help would be appreciated.
EDIT: changed to unsigned long int and it worked. Thanks everyone!
In fact your solution is too small rather than too big. The answer is what was pointed out in the comments, that there is integer overflow, and the clue is in the fact that your solution is close to the largest possible value for an signed int: 2147483647. You need to use a different type to store the product.
Note that the answer below is still 'correct' in that your code does do this wrong, but it's not what is causing the wrong value. Try taking your (working) code to http://codereview.stackexchange.com if you would like the folks there to tell you what you could improve in your approach and your coding style.
Previous answer
You are checking for a new greatest product inside the inner loop instead of outside. This means that your maximum includes all strings of less or equal ton 13 digits, rather than only exactly 13.
This could make a difference if you are finding a string which has fewer than 13 digits which have a large product, but a 0 at either end. You shouldn't count this as the largest, but your code does. (I haven't checked if this does actually happen.)
for (int i=0; i < num.length() -12; i++)
{
product = ((int) num[i] - 48);
for (int j=i+1; j<i+13; j++)
{
product = product * ((int) num[j] - 48);
}
if (greatestProduct <= product)
{
greatestProduct = product;
}
}
9^13 ≈ 2.54e12 (maximal possible value, needs 42 bit to be represented exactly), which doesn't fit into signed int. You should use int64.
If you don't want to mess with BigNum libraries, you could just take logarithms of your digits (rejecting 0) and add them up. It amounts to the same comparison.
A faster way without internal loop, but works only where there isn't a 0 in the input:
long long greatest(string num)
{
if (num.length() < 13)
return 0;
// Find a product of first 13 numbers.
long long product = 1;
unsigned int i;
for (i=0; i<13; ++i) {
product *= (num[i]-'0');
}
long long greatest_product = product;
// move through the large number
for (i=0; i+13<num.length(); ++i) {
product = product/(num[i]-'0')*(num[i+13]-'0');
if (greatest_product < product)
greatest_product = product;
}
return greatest_product;
}
In order to make this work with inputs containing 0, split the input string into substrings:
int main()
{
string num = /* input value*/;
long long greatest_product = 0;
size_t start = -1;
// Iterate over substrings without zero
do {
++start;
size_t end = num.find('0', start);
long long product = greatest(num.substr(start, end-start));
if (greatest_product < product)
greatest_product = product;
start = end;
} while (start != string::npos);
cout << greatest_product << endl;
}
My functional programming solution
def product(number):
product_result = 1
for n in number:
product_result *= int(n)
return product_result
length = 13
indices = range(0, len(number) - 13 + 1)
values = indices
values = map(lambda index: {"index": index, "number": number}, values)
values = map(lambda value: value["number"][value["index"]:value["index"] + length], values)
values = map(product, values)
values = max(values)
print values
public static void main(String[] args) {
String val = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
int Sum = 0;
String adjacent = null;
for (int i = 0; i < val.length()-13; i++) {
int total = 1;
for (int j = 0; j < 13; j++) {
total = total * Character.getNumericValue(val.charAt(i+j));
}
if(total > Sum){
Sum = total;
adjacent = val.substring(i, i+13);
}
}
System.out.println("Sum = " + Sum);
System.out.println("Adjsc = " + adjacent );
}
I had the same problem.
int product and int greatestproduct have maximum value it can store since they are 'int' type. They can only store values up to 2147483647.
Use 'long long' type instead of 'int'.
const thousandDigit =
`73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450`;
const productsOfAdjacentNths = num =>
[...thousandDigit].reduce((acc, _, idx) => {
const nthDigitAdjX = [...thousandDigit.substr(idx, num)].reduce(
(inAcc, inCur) => inCur * inAcc,
1
);
return acc.concat(nthDigitAdjX);
}, []);
console.log(Math.max(...productsOfAdjacentNths(13))); //5377010688
This is my O(n) approach
function findLargest(digits, n){
let largest = 0;
let j = 0;
let res = 1;
for(let i = 0; i< digits.length; i ++){
res = res * parseInt(digits[i]);
if(res == 0){
res = 1;
j = 0;
continue;
}
if(j === n-1){
if(res > largest)
largest = res;
res = res/parseInt(digits[i - j]);
j = j - 1;
}
j = j + 1;
}
return largest;
}
let val = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
findLargest(val, 13);
Although above solutions are good, here is a python implementation which works perfectly:
def main():
num=7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
prod,maxprod=1,0
numtostr=str(num)
length=len(numtostr)
for i in range(1,length-13+1):
prod=1
for z in range(i,i+13):
prod=prod*int(numtostr[z-1:z])
if prod>maxprod:
maxprod=prod
print "Largest 13 digit product is %d" %(maxprod)
if __name__ == '__main__':
main()
static long q8(){
long max_product = 1;
long product = 1;
String n = "LONG_INPUT";
for(int i=0;i<13;i++){
max_product *= Integer.parseInt(n.charAt(i)+"");
}
product = max_product;
for(int i=1;i<n.length()-13;i++){
int denom = Integer.parseInt(n.charAt(i-1)+"");
if(denom!=0)
product = product/denom * Integer.parseInt(n.charAt(i+12)+"");
else
product = product(i,n);
max_product = (max_product>product)?max_product:product;
}
return max_product;
}
static long product(int index,String n){
long pro = 1;
for(int i=index;i<index+13;i++){
pro *= Integer.parseInt(n.charAt(i)+"");
}
return pro;
}
Try this:
{
DateTime BeganAt = new DateTime();
BeganAt = DateTime.Now;
Int64 result = 0;
string testNumber = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
StringBuilder StringBuilder = new StringBuilder(13);
Int64 maxNumber = 0;
try
{
char[] numbers = testNumber.ToCharArray();
int tempCounter = 13;
for (int i = 0;i < numbers.Length;i++)
{
if(i < tempCounter)
{
StringBuilder.Append(numbers[i]);
}
else if (i == tempCounter)
{
if (maxNumber < Convert.ToInt64(StringBuilder.ToString()))
{
maxNumber = Convert.ToInt64(StringBuilder.ToString());
}
StringBuilder.Clear();
StringBuilder.Append(numbers[i]);
tempCounter = tempCounter + n;
}
}
result = maxNumber;
}
catch
{
throw;
}
DateTime EndedAt = new DateTime();
EndedAt = DateTime.Now;
TimeSpan TimeItTook = (EndedAt - BeganAt);
return Convert.ToString(result) + " - Time took to execute: " + Convert.ToString(TimeItTook.TotalMilliseconds);
}
long long int sum = 1,high=0;
for (int i = 0; i < 988; i++)
{
sum = sum*(arr[i] - 48);
for (int j = i + 1; j < i+13; j++)
{
sum = sum*(arr[j]-48);
}
if (sum >= high)
{
high = sum;
}
sum = 1;
}
My solution to above problem if someone is still watching this in 2018.Although there are lots of solution to this question here my solution pre-checks the individual 13 digits which have a 0 in them.As something multiplied with 0 is always 0 so we can remove this useless computation
int j = 0, k = 12;
long long int mult = 1;
long long int max = 0;
char *digits = /*Big number*/
while(k < 1000){
for (int i = j; i <= k; ++i)
{
/* code */
long long int val = digits[i] -'0';
/* check if any number in series contains 0 */
if(val == 0){
break;
}
mult = mult * val;
}
printf("mult is %lld\n",mult );
/* check for max value */
if(max < mult){
max = mult;
}
printf("the new max is %lld\n", max);
j += 1;
k += 1;
mult = 1;
printf("%d iteration finished\n", k);
}
printf("%lld\n", max);
You should use 'int64_t' at the place of 'int'
I have solve this problem using python 're' module
Finding all possible 13 digits number without having zeros (total 988 with zero and 283 without zero) then find the product of each of these digits and check for max
here i have used look ahead regex
Note: string must not contain any newline char
s = '731671765...'
import re
def product_13(d):
pro = 1
while d:
pro *= d % 10
d //= 10
return pro
pat = re.compile(r'(?=([1-9]{13}))')
all = map(int, re.findall(pat, s))
pro = -1
for i in all:
v = product_13(i)
if pro < v:
pro = v
print(pro)
**This is JavaScript solution.**
greatestProductOfAdjacentDigit = (givenNumber, noOfDigit) => {
stringNumberToNumbers = givenNumber => givenNumber.split('').map(each => parseInt(each, 10))
let numbers = mathematicalProblems.stringNumberToNumbers(givenNumber);
return numbers.map(function (each, ind, arr) {
return mathematicalProblems.productOfAll(arr.slice(ind, ind + noOfDigit));
}).reduce(function (accumulator, currentValue) {
return accumulator > currentValue ? accumulator : currentValue;
});
};
Testing
const givenNumber = '73167176531330624919225119674426574742355349' +
'194934969835203127745063262395783180169848018694788518438586' +
'156078911294949545950173795833195285320880551112540698747158' +
'523863050715693290963295227443043557668966489504452445231617' +
'318564030987111217223831136222989342338030813533627661428280' +
'644448664523874930358907296290491560440772390713810515859307' +
'960866701724271218839987979087922749219016997208880937766572' +
'733300105336788122023542180975125454059475224352584907711670' +
'556013604839586446706324415722155397536978179778461740649551' +
'492908625693219784686224828397224137565705605749026140797296' +
'865241453510047482166370484403199890008895243450658541227588' +
'666881164271714799244429282308634656748139191231628245861786' +
'645835912456652947654568284891288314260769004224219022671055' +
'626321111109370544217506941658960408071984038509624554443629' +
'812309878799272442849091888458015616609791913387549920052406' +
'368991256071760605886116467109405077541002256983155200055935' +
'72972571636269561882670428252483600823257530420752963450';
console.log(greatestProductOfAdjacentDigit(givenNumber, 4)); //5832
console.log(greatestProductOfAdjacentDigit(givenNumber, 13)); //23514624000
My 2 cents ... Javascript
Largest_product_in_series_13 = g => {
return [...g.matchAll(/(?=([1-9]{13}))/g)]
.reduce((a,c)=>(p=eval(c[1].split``.join`*`),p>a?p:a),0)
}
First it matches all 13 digit series, then it reduces to the biggest product.
console.log(Largest_product_in_series_13(`7316717653133062491922....
> 23514624000
start: 14.292ms
I solved it using ruby. if
x = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"
then used below logic to solve the problem
def print_lps(x)
p = 1
0.upto(x.length-13) do |i|
j = i
xy = 1
while j < i+13 do
xy *= x[j].to_i
j += 1
end
p = xy if xy > p
end
puts p
end
print_lps(x) # 23514624000
I solve the problem using this approach
1.Run two loops first outer loop which iterate over numbers in the string.
2.Inner loop reach to next 13 numbers afterwards and store its product in a variable
3.As inner loop ends we only use maximum value.(that what we need) :>
Have a look at my code in C++
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s="//thestring is there";
long long unsigned mainans=1,ans=1; //initialize the value of mainans and ans to 1 (not 0 as product also become 0)
for(int i=0;i<s.length()-13;i++) //run the loop from 0 upto 13 minus string length
{
ans=1;
for(int j=i;j<i+13;j++) //now from that particular digit we check 13 digits afterwards it
{
int m=s[j]-'0'; //convert the number from string to integer
ans*=m; //taking product in every interation for 13 digits
}
mainans=max(mainans,ans); //now taking only max value because that what we need
}
cout<<mainans;
return 0;
}
This will find the answer in O(n) time and it handles zero. Written in Dart.
/**
* Main function
*
* Find the thirteen adjacent digits in the 1000-digit number that have the greatest product.
* What is the value of this product?
*
*/
const String DIGITS = "73167176531330624919225119674426574742355349194934"
"96983520312774506326239578318016984801869478851843"
"85861560789112949495459501737958331952853208805511"
"12540698747158523863050715693290963295227443043557"
"66896648950445244523161731856403098711121722383113"
"62229893423380308135336276614282806444486645238749"
"30358907296290491560440772390713810515859307960866"
"70172427121883998797908792274921901699720888093776"
"65727333001053367881220235421809751254540594752243"
"52584907711670556013604839586446706324415722155397"
"53697817977846174064955149290862569321978468622482"
"83972241375657056057490261407972968652414535100474"
"82166370484403199890008895243450658541227588666881"
"16427171479924442928230863465674813919123162824586"
"17866458359124566529476545682848912883142607690042"
"24219022671055626321111109370544217506941658960408"
"07198403850962455444362981230987879927244284909188"
"84580156166097919133875499200524063689912560717606"
"05886116467109405077541002256983155200055935729725"
"71636269561882670428252483600823257530420752963450";
main(List<String> args) {
const int MAX_DIGITS = 13;
int len = DIGITS.length;
int digits = 0;
int largest = 0;
int current = 0;
int index = 0;
while (index < len) {
int value = int.parse(DIGITS[index]);
// if we get a zero then rebuild the MAX_DIGITS consecutive digits
if (value == 0) {
current = 0;
digits = 0;
} else {
// Multiply consecutive digits up to target set
if (digits < MAX_DIGITS) {
if (current == 0) {
current = value;
} else
current *= value;
digits++;
} else {
int divisor = int.parse(DIGITS[index - MAX_DIGITS]);
if (current == 0) {
current = value;
} else {
current = (current ~/ divisor);
current *= value;
}
}
if (current > largest) {
largest = current;
}
}
index++;
}
print('Num $largest');
}

How to read binary files properly?

I have a problem with the NIST/Diehard Binary Matrix test. It's about dividing a binary sequence into a 32x32 matrix and calculating its rank. After calculating ranks I need to compute a xi^2 value and then calculate p-value(must be from 0 to 1). I'm getting p-value extremely small even in a random sequence.
I've tried to hardcode some small examples and getting my p-value right though I think my problem is in reading a binary sequence file and getting bits from it.
This is reading from a file and converting to bits sequence.
ifstream fin("seq1.bin", ios::binary);
fin.seekg(0, ios::end);
int n = fin.tellg();
unsigned int start, end;
char *buf = new char[n];
fin.seekg(0, ios::beg);
fin.read(buf, n);
n *= 8;
bool *s = new bool[n];
for (int i = 0; i < n / 8; i++) {
for (int j = 7; j >= 0; j--) {
s[(i) * 8 + 7 - j] = (bool)((buf[i] >> j) & 1);
}
}
Then I form my matrix and calculate it's rank
int *ranks = new int[N];
for (int i = 0; i < N; i++) {
bool *arr = new bool[m*q];
copy(s + i * m*q, s +(i * m*q) + (m * q), arr);
ranks[i] = binary_rank(arr, m, q);
}
Cheking occurance in ranks
int count_occurrences(int arr[], int n, int x){
int result = 0;
for (int i = 0; i < n; i++)
if (x == arr[i])
result++;
return result;
}
Calculating xi^2 and p-value
double calculate_xi(int fm, int fm_1, int remaining, int N) {
double N1 = 0.2888*N;
double N2 = 0.5776*N;
double N3 = 0.1336*N;
double x1 = (fm - N1)*(fm - N1) / N1;
double x2 = (fm_1 - N2)*(fm_1 - N2) / N2;
double x3 = (remaining - N3)*(remaining - N3) / N3;
return x1 + x2 + x3;
}
double calculate_pvalue(double xi2) {
return exp(-(xi2 / 2));
}
I expect p-value between 0 and 1 but getting 0 every time. It's because of the extremely big xi^2 value and I couldn't find what I've done wrong. Could you please help me to get things right.
For this part:
for (int i = 0; i < n / 8; i++) {
for (int j = 7; j >= 0; j--) {
s[(i) * 8 + 7 - j] = (bool)((buf[i] >> j) & 1);
}
}
when you add elements to s array, looks like you switch the position of bytes inside each character: the last bit in character in buf goes into the first bit in character in s array, because the shift initially is 7, so you take first bit in char from buf[], but for s[] it looks to be 0, resulting in swapping. It is easy to verify with debugger though, as from code it is not so obvious. Thanks.

Convert string to float or integer without using built in functions (like atoi or atof)

I'm new to C++ and our teacher asked us to get a function that does the above title. So far I've got a function that converts a string to an integer, but I have no idea about how to modify it to make it work if the numbers in the string would represent a float.
int convert(char str[], int size) {
int number = 0;
for (int i = 0; i < size; ++i) {
number += (str[i] - 48)*pow(10, (size - i - 1));
}
return number;
}
If I run:
char myString[] = "12345";
convert(myString, 5);
I get:
12345
But if I run:
char myString[] = "123.45";
convert(myString, 5);
I get:
122845
How could I modify my program to work with floats too? I know convert function is meant to return an int so, should I use two more functions?
I was thinking about one that determinates if the string is inteded to be converted to an integer or a string, and the other that'll actually convert the string to a float.
Here is the function for doing so...
template<class T, class S>
T convert_string_to_number(S s)
{
auto result = T(0.l);
if (s.back() == L'F' || s.back() == L'f')
s = s.substr(0u, s.size() - 1u);
auto temp = s;
auto should_add = false;
if (!std::is_floating_point<T>::value)
{
should_add = temp.at(temp.find_first_of(L'.') + 1) >= '5';
temp.erase(temp.begin() + temp.find_first_of(L'.'), temp.end());
}
else if (temp.find_first_of(L'.') != S::npos)
temp.erase(temp.begin() + temp.find_first_of(L'.'));
for (int i = temp.size() - 1u; i >= 0; --i)
if (temp[i] >= L'0' && temp[i] <= L'9')
result += T(std::powl(10.l, temp.size() - i - 1.l) * (temp[i] - L'0'));
else
throw std::invalid_argument("Invalid numerical string!");
if (s.find(L'-') != S::npos)
result = -T(std::fabs(result));
if (s.find(L'.') != S::npos && std::is_floating_point<T>::value)
result /= T(std::powl(10.l, s.size() - s.find(L'.') - 1.l));
return std::is_floating_point<T>::value ? T(result) : T(result + T(should_add));
}
Just use it like you typically would...
auto some_number = convert_string_to_number<float>(myString);...
For the floating point part of the assignment: what about regular expressions? It is also kind of built-in functionality, but general purpose, not designed for your particular task, so I hope your teacher will be fine with this idea.
You can use the following regex: [+-]?([0-9]*[.])?[0-9]+ (I got it from this answer) to detect if provided string is a floating point number. Then you can modify the expression a little bit to capture the +/- signs and parts before/after the dot separator. Once you extract these features the task should be relatively simple.
Also please change your method signature to: float convert(const std::string& str).
Try this :
int convert(char str[], int size) {
int number = 0;
for (int i = 0; i < size; ++i) {
number += (str[i] - 48)*pow(10, (size - i - 1));
}
return number;
}
int pow10(int radix)
{
int r = 1;
for (int i = 0; i < radix; i++)
r *= 10;
return r;
}
float convert2float(char str[], int size) { //size =6
// convert to string_without_decimal
char str_without_decimal[10];
int c = 0;
for (int i = 0; i < size; i++)
{
if (str[i] >= 48 && str[i] <= 57) {
str_without_decimal[c] = str[i];
c++;
}
}
str_without_decimal[c] = '\0'; //str_without_decimal = "12345"
//adjust size if dot present or not. If no dot present => size = c
size = (size != c ?) size - 1 : size; //size = 5 = 6-1 since dot is present
//convert to decimal
int decimal = convert(str_without_decimal, size); //decimal = 12345
//get divisor
int i;
for (i = size; i >= 0; i--) {
if (str[i] == '.') break;
}
int divisor = pow10(size - i); //divisor = 10;
return (float)decimal/(float) divisor; // result = 12345 /10
}
int main()
{
char str[] = "1234.5";
float f = convert2float(str, 6);
cout << f << endl;
return 0;
}

Project Euler #8, I don't understand where I'm going wrong

I'm working on project euler problem number eight, in which ive been supplied this ridiculously large number:
7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
and am supposed to "Find the thirteen adjacent digits in the 1000-digit number that have the greatest product." EG the product of the first four adjacent digits is 7 * 3 * 1 * 6.
My code is the following:
int main()
{
string num = /* ridiculously large number omitted */;
int greatestProduct = 0;
int product;
for (int i=0; i < num.length() -12; i++)
{
product = ((int) num[i] - 48);
for (int j=i+1; j<i+13; j++)
{
product = product * ((int) num[j] - 48);
if (greatestProduct <= product)
{
greatestProduct = product;
}
}
}
cout << greatestProduct << endl;
}
I keep getting 2091059712 as the answer which project euler informs me is wrong and I suspect its too large anyway. Any help would be appreciated.
EDIT: changed to unsigned long int and it worked. Thanks everyone!
In fact your solution is too small rather than too big. The answer is what was pointed out in the comments, that there is integer overflow, and the clue is in the fact that your solution is close to the largest possible value for an signed int: 2147483647. You need to use a different type to store the product.
Note that the answer below is still 'correct' in that your code does do this wrong, but it's not what is causing the wrong value. Try taking your (working) code to http://codereview.stackexchange.com if you would like the folks there to tell you what you could improve in your approach and your coding style.
Previous answer
You are checking for a new greatest product inside the inner loop instead of outside. This means that your maximum includes all strings of less or equal ton 13 digits, rather than only exactly 13.
This could make a difference if you are finding a string which has fewer than 13 digits which have a large product, but a 0 at either end. You shouldn't count this as the largest, but your code does. (I haven't checked if this does actually happen.)
for (int i=0; i < num.length() -12; i++)
{
product = ((int) num[i] - 48);
for (int j=i+1; j<i+13; j++)
{
product = product * ((int) num[j] - 48);
}
if (greatestProduct <= product)
{
greatestProduct = product;
}
}
9^13 ≈ 2.54e12 (maximal possible value, needs 42 bit to be represented exactly), which doesn't fit into signed int. You should use int64.
If you don't want to mess with BigNum libraries, you could just take logarithms of your digits (rejecting 0) and add them up. It amounts to the same comparison.
A faster way without internal loop, but works only where there isn't a 0 in the input:
long long greatest(string num)
{
if (num.length() < 13)
return 0;
// Find a product of first 13 numbers.
long long product = 1;
unsigned int i;
for (i=0; i<13; ++i) {
product *= (num[i]-'0');
}
long long greatest_product = product;
// move through the large number
for (i=0; i+13<num.length(); ++i) {
product = product/(num[i]-'0')*(num[i+13]-'0');
if (greatest_product < product)
greatest_product = product;
}
return greatest_product;
}
In order to make this work with inputs containing 0, split the input string into substrings:
int main()
{
string num = /* input value*/;
long long greatest_product = 0;
size_t start = -1;
// Iterate over substrings without zero
do {
++start;
size_t end = num.find('0', start);
long long product = greatest(num.substr(start, end-start));
if (greatest_product < product)
greatest_product = product;
start = end;
} while (start != string::npos);
cout << greatest_product << endl;
}
My functional programming solution
def product(number):
product_result = 1
for n in number:
product_result *= int(n)
return product_result
length = 13
indices = range(0, len(number) - 13 + 1)
values = indices
values = map(lambda index: {"index": index, "number": number}, values)
values = map(lambda value: value["number"][value["index"]:value["index"] + length], values)
values = map(product, values)
values = max(values)
print values
public static void main(String[] args) {
String val = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
int Sum = 0;
String adjacent = null;
for (int i = 0; i < val.length()-13; i++) {
int total = 1;
for (int j = 0; j < 13; j++) {
total = total * Character.getNumericValue(val.charAt(i+j));
}
if(total > Sum){
Sum = total;
adjacent = val.substring(i, i+13);
}
}
System.out.println("Sum = " + Sum);
System.out.println("Adjsc = " + adjacent );
}
I had the same problem.
int product and int greatestproduct have maximum value it can store since they are 'int' type. They can only store values up to 2147483647.
Use 'long long' type instead of 'int'.
const thousandDigit =
`73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450`;
const productsOfAdjacentNths = num =>
[...thousandDigit].reduce((acc, _, idx) => {
const nthDigitAdjX = [...thousandDigit.substr(idx, num)].reduce(
(inAcc, inCur) => inCur * inAcc,
1
);
return acc.concat(nthDigitAdjX);
}, []);
console.log(Math.max(...productsOfAdjacentNths(13))); //5377010688
This is my O(n) approach
function findLargest(digits, n){
let largest = 0;
let j = 0;
let res = 1;
for(let i = 0; i< digits.length; i ++){
res = res * parseInt(digits[i]);
if(res == 0){
res = 1;
j = 0;
continue;
}
if(j === n-1){
if(res > largest)
largest = res;
res = res/parseInt(digits[i - j]);
j = j - 1;
}
j = j + 1;
}
return largest;
}
let val = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
findLargest(val, 13);
Although above solutions are good, here is a python implementation which works perfectly:
def main():
num=7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
prod,maxprod=1,0
numtostr=str(num)
length=len(numtostr)
for i in range(1,length-13+1):
prod=1
for z in range(i,i+13):
prod=prod*int(numtostr[z-1:z])
if prod>maxprod:
maxprod=prod
print "Largest 13 digit product is %d" %(maxprod)
if __name__ == '__main__':
main()
static long q8(){
long max_product = 1;
long product = 1;
String n = "LONG_INPUT";
for(int i=0;i<13;i++){
max_product *= Integer.parseInt(n.charAt(i)+"");
}
product = max_product;
for(int i=1;i<n.length()-13;i++){
int denom = Integer.parseInt(n.charAt(i-1)+"");
if(denom!=0)
product = product/denom * Integer.parseInt(n.charAt(i+12)+"");
else
product = product(i,n);
max_product = (max_product>product)?max_product:product;
}
return max_product;
}
static long product(int index,String n){
long pro = 1;
for(int i=index;i<index+13;i++){
pro *= Integer.parseInt(n.charAt(i)+"");
}
return pro;
}
Try this:
{
DateTime BeganAt = new DateTime();
BeganAt = DateTime.Now;
Int64 result = 0;
string testNumber = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
StringBuilder StringBuilder = new StringBuilder(13);
Int64 maxNumber = 0;
try
{
char[] numbers = testNumber.ToCharArray();
int tempCounter = 13;
for (int i = 0;i < numbers.Length;i++)
{
if(i < tempCounter)
{
StringBuilder.Append(numbers[i]);
}
else if (i == tempCounter)
{
if (maxNumber < Convert.ToInt64(StringBuilder.ToString()))
{
maxNumber = Convert.ToInt64(StringBuilder.ToString());
}
StringBuilder.Clear();
StringBuilder.Append(numbers[i]);
tempCounter = tempCounter + n;
}
}
result = maxNumber;
}
catch
{
throw;
}
DateTime EndedAt = new DateTime();
EndedAt = DateTime.Now;
TimeSpan TimeItTook = (EndedAt - BeganAt);
return Convert.ToString(result) + " - Time took to execute: " + Convert.ToString(TimeItTook.TotalMilliseconds);
}
long long int sum = 1,high=0;
for (int i = 0; i < 988; i++)
{
sum = sum*(arr[i] - 48);
for (int j = i + 1; j < i+13; j++)
{
sum = sum*(arr[j]-48);
}
if (sum >= high)
{
high = sum;
}
sum = 1;
}
My solution to above problem if someone is still watching this in 2018.Although there are lots of solution to this question here my solution pre-checks the individual 13 digits which have a 0 in them.As something multiplied with 0 is always 0 so we can remove this useless computation
int j = 0, k = 12;
long long int mult = 1;
long long int max = 0;
char *digits = /*Big number*/
while(k < 1000){
for (int i = j; i <= k; ++i)
{
/* code */
long long int val = digits[i] -'0';
/* check if any number in series contains 0 */
if(val == 0){
break;
}
mult = mult * val;
}
printf("mult is %lld\n",mult );
/* check for max value */
if(max < mult){
max = mult;
}
printf("the new max is %lld\n", max);
j += 1;
k += 1;
mult = 1;
printf("%d iteration finished\n", k);
}
printf("%lld\n", max);
You should use 'int64_t' at the place of 'int'
I have solve this problem using python 're' module
Finding all possible 13 digits number without having zeros (total 988 with zero and 283 without zero) then find the product of each of these digits and check for max
here i have used look ahead regex
Note: string must not contain any newline char
s = '731671765...'
import re
def product_13(d):
pro = 1
while d:
pro *= d % 10
d //= 10
return pro
pat = re.compile(r'(?=([1-9]{13}))')
all = map(int, re.findall(pat, s))
pro = -1
for i in all:
v = product_13(i)
if pro < v:
pro = v
print(pro)
**This is JavaScript solution.**
greatestProductOfAdjacentDigit = (givenNumber, noOfDigit) => {
stringNumberToNumbers = givenNumber => givenNumber.split('').map(each => parseInt(each, 10))
let numbers = mathematicalProblems.stringNumberToNumbers(givenNumber);
return numbers.map(function (each, ind, arr) {
return mathematicalProblems.productOfAll(arr.slice(ind, ind + noOfDigit));
}).reduce(function (accumulator, currentValue) {
return accumulator > currentValue ? accumulator : currentValue;
});
};
Testing
const givenNumber = '73167176531330624919225119674426574742355349' +
'194934969835203127745063262395783180169848018694788518438586' +
'156078911294949545950173795833195285320880551112540698747158' +
'523863050715693290963295227443043557668966489504452445231617' +
'318564030987111217223831136222989342338030813533627661428280' +
'644448664523874930358907296290491560440772390713810515859307' +
'960866701724271218839987979087922749219016997208880937766572' +
'733300105336788122023542180975125454059475224352584907711670' +
'556013604839586446706324415722155397536978179778461740649551' +
'492908625693219784686224828397224137565705605749026140797296' +
'865241453510047482166370484403199890008895243450658541227588' +
'666881164271714799244429282308634656748139191231628245861786' +
'645835912456652947654568284891288314260769004224219022671055' +
'626321111109370544217506941658960408071984038509624554443629' +
'812309878799272442849091888458015616609791913387549920052406' +
'368991256071760605886116467109405077541002256983155200055935' +
'72972571636269561882670428252483600823257530420752963450';
console.log(greatestProductOfAdjacentDigit(givenNumber, 4)); //5832
console.log(greatestProductOfAdjacentDigit(givenNumber, 13)); //23514624000
My 2 cents ... Javascript
Largest_product_in_series_13 = g => {
return [...g.matchAll(/(?=([1-9]{13}))/g)]
.reduce((a,c)=>(p=eval(c[1].split``.join`*`),p>a?p:a),0)
}
First it matches all 13 digit series, then it reduces to the biggest product.
console.log(Largest_product_in_series_13(`7316717653133062491922....
> 23514624000
start: 14.292ms
I solved it using ruby. if
x = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"
then used below logic to solve the problem
def print_lps(x)
p = 1
0.upto(x.length-13) do |i|
j = i
xy = 1
while j < i+13 do
xy *= x[j].to_i
j += 1
end
p = xy if xy > p
end
puts p
end
print_lps(x) # 23514624000
I solve the problem using this approach
1.Run two loops first outer loop which iterate over numbers in the string.
2.Inner loop reach to next 13 numbers afterwards and store its product in a variable
3.As inner loop ends we only use maximum value.(that what we need) :>
Have a look at my code in C++
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s="//thestring is there";
long long unsigned mainans=1,ans=1; //initialize the value of mainans and ans to 1 (not 0 as product also become 0)
for(int i=0;i<s.length()-13;i++) //run the loop from 0 upto 13 minus string length
{
ans=1;
for(int j=i;j<i+13;j++) //now from that particular digit we check 13 digits afterwards it
{
int m=s[j]-'0'; //convert the number from string to integer
ans*=m; //taking product in every interation for 13 digits
}
mainans=max(mainans,ans); //now taking only max value because that what we need
}
cout<<mainans;
return 0;
}
This will find the answer in O(n) time and it handles zero. Written in Dart.
/**
* Main function
*
* Find the thirteen adjacent digits in the 1000-digit number that have the greatest product.
* What is the value of this product?
*
*/
const String DIGITS = "73167176531330624919225119674426574742355349194934"
"96983520312774506326239578318016984801869478851843"
"85861560789112949495459501737958331952853208805511"
"12540698747158523863050715693290963295227443043557"
"66896648950445244523161731856403098711121722383113"
"62229893423380308135336276614282806444486645238749"
"30358907296290491560440772390713810515859307960866"
"70172427121883998797908792274921901699720888093776"
"65727333001053367881220235421809751254540594752243"
"52584907711670556013604839586446706324415722155397"
"53697817977846174064955149290862569321978468622482"
"83972241375657056057490261407972968652414535100474"
"82166370484403199890008895243450658541227588666881"
"16427171479924442928230863465674813919123162824586"
"17866458359124566529476545682848912883142607690042"
"24219022671055626321111109370544217506941658960408"
"07198403850962455444362981230987879927244284909188"
"84580156166097919133875499200524063689912560717606"
"05886116467109405077541002256983155200055935729725"
"71636269561882670428252483600823257530420752963450";
main(List<String> args) {
const int MAX_DIGITS = 13;
int len = DIGITS.length;
int digits = 0;
int largest = 0;
int current = 0;
int index = 0;
while (index < len) {
int value = int.parse(DIGITS[index]);
// if we get a zero then rebuild the MAX_DIGITS consecutive digits
if (value == 0) {
current = 0;
digits = 0;
} else {
// Multiply consecutive digits up to target set
if (digits < MAX_DIGITS) {
if (current == 0) {
current = value;
} else
current *= value;
digits++;
} else {
int divisor = int.parse(DIGITS[index - MAX_DIGITS]);
if (current == 0) {
current = value;
} else {
current = (current ~/ divisor);
current *= value;
}
}
if (current > largest) {
largest = current;
}
}
index++;
}
print('Num $largest');
}

How can I pad my md5 message with c/c++

I'm working on a program in c++ to do md5 checksums. I'm doing this mainly because I think I'll learn a lot of different things about c++, checksums, OOP, and whatever else I run into.
I'm having trouble the check sums and I think the problem is in the function padbuff which does the message padding.
#include "HashMD5.h"
int leftrotate(int x, int y);
void padbuff(uchar * buffer);
//HashMD5 constructor
HashMD5::HashMD5()
{
Type = "md5";
Hash = "";
}
HashMD5::HashMD5(const char * hashfile)
{
Type = "md5";
std::ifstream filestr;
filestr.open(hashfile, std::fstream::in | std::fstream::binary);
if(filestr.fail())
{
std::cerr << "File " << hashfile << " was not opened.\n";
std::cerr << "Open failed with error ";
}
}
std::string HashMD5::GetType()
{
return this->Type;
}
std::string HashMD5::GetHash()
{
return this->Hash;
}
bool HashMD5::is_open()
{
return !((this->filestr).fail());
}
void HashMD5::CalcHash(unsigned int * hash)
{
unsigned int *r, *k;
int r2[4] = {0, 4, 9, 15};
int r3[4] = {0, 7, 12, 19};
int r4[4] = {0, 4, 9, 15};
uchar * buffer;
int bufLength = (2<<20)*8;
int f,g,a,b,c,d, temp;
int *head;
uint32_t maxint = 1<<31;
//Initialized states
unsigned int h[4]{ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
r = new unsigned int[64];
k = new unsigned int[64];
buffer = new uchar[bufLength];
if(r==NULL || k==NULL || buffer==NULL)
{
std::cerr << "One of the dyn alloc failed\n";
}
// r specifies the per-round shift amounts
for(int i = 0; i<16; i++)
r[i] = 7 + (5 * ((i)%4) );
for(int i = 16; i < 32; i++)
r[i] = 5 + r2[i%4];
for(int i = 32; i< 48; i++)
r[i] = 4 + r3[i%4];
for(int i = 48; i < 63; i++)
r[i] = 6 + r4[i%4];
for(int i = 0; i < 63; i++)
{
k[i] = floor( fabs( sin(i + 1)) * maxint);
}
while(!(this->filestr).eof())
{
//Read in 512 bits
(this->filestr).read((char *)buffer, bufLength-512);
padbuff(buffer);
//The 512 bits are now 16 32-bit ints
head = (int *)buffer;
for(int i = 0; i < 64; i++)
{
if(i >=0 && i <=15)
{
f = (b & c) | (~b & d);
g = i;
}
else if(i >= 16 && i <=31)
{
f = (d & b) | (~d & b);
g = (5*i +1) % 16;
}
else if(i >=32 && i<=47)
{
f = b ^ c ^ d;
g = (3*i + 5 ) % 16;
}
else
{
f = c ^ (b | ~d);
g = (7*i) % 16;
}
temp = d;
d = c;
c = b;
b = b + leftrotate((a + f + k[i] + head[g]), r[i]);
a = temp;
}
h[0] +=a;
h[1] +=b;
h[2] +=c;
h[3] +=d;
}
delete[] r;
delete[] k;
hash = h;
}
int leftrotate(int x, int y)
{
return(x<<y) | (x >> (32 -y));
}
void padbuff(uchar* buffer)
{
int lack;
int length = strlen((char *)buffer);
uint64_t mes_size = length % UINT64_MAX;
if((lack = (112 - (length % 128) ))>0)
{
*(buffer + length) = ('\0'+1 ) << 3;
memset((buffer + length + 1),0x0,lack);
memcpy((void*)(buffer+112),(void *)&mes_size, 64);
}
}
In my test program I run this on the an empty message. Thus length in padbuff is 0. Then when I do *(buffer + length) = ('\0'+1 ) << 3;, I'm trying to pad the message with a 1. In the Netbeans debugger I cast buffer as a uint64_t and it says buffer=8. I was trying to put a 1 bit in the most significant spot of buffer so my cast should have been UINT64_MAX. Its not, so I'm confused about how my padding code works. Can someone tell me what I'm doing and what I'm supposed to do in padbuff? Thanks, and I apologize for the long freaking question.
Just to be clear about what the padding is supposed to be doing, here is the padding excerpt from Wikipedia:
The message is padded so that its length is divisible by 512. The padding works as follows: first a single bit, 1, is appended to the end of the message. This is followed by as many zeros as are required to bring the length of the message up to 64 bits fewer than a multiple of 512. The remaining bits are filled up with 64 bits representing the length of the original message, modulo 264.
I'm mainly looking for help for padbuff, but since I'm trying to learn all comments are appreciated.
The first question is what you did:
length % UINT64_MAX doesn't make sense at all because length is in bytes and MAX is the value you can store in UINT64.
You thought that putting 1 bit in the most significant bit would give the maximum value. In fact, you need to put 1 in all bits to get it.
You shift 1 by 3. It's only half the length of the byte.
The byte pointed by buffer is the least significant in little endian. (I assume you have little endian since the debugger showed 8).
The second question how it should work.
I don't know what exactly padbuff should do but if you want to pad and get UINT64_MAX, you need something like this:
int length = strlen((char *)buffer);
int len_of_padding = sizeof(uint64_t) - length % sizeof(uint64_t);
if(len_of_padding > 0)
{
memset((void*)(buffer + length), 0xFF, len_of_padding);
}
You worked with the length of two uint64 values. May be you wanted to zero the next one:
uint64_t *after = (uint64_t*)(buffer + length + len_of_padding);
*after = 0;