Skip to content

Commit

Permalink
solve p22 in c++
Browse files Browse the repository at this point in the history
  • Loading branch information
LivInTheLookingGlass committed Aug 5, 2024
1 parent 3a01caf commit db41f27
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Olivia's Project Euler Solutions
| | |gcc|, |pcc|, |tcc| |br| | | |C-Cov| |br| |
| | C11+ in: |msvc| [1]_ | | |CodeQL| |
+------------+--------------------------+--------+-------------------+
| C++ | C++98+ in: |br| |clang| | 13 | |Cpi| |br| |
| C++ | C++98+ in: |br| |clang| | 14 | |Cpi| |br| |
| | |gcc| |br| | | |Cp-Cov| |br| |
| | C++14+ in: |msvc| [1]_ | | |CodeQL| |
+------------+--------------------------+--------+-------------------+
Expand Down
1 change: 1 addition & 0 deletions cplusplus/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Problems Solved
- ☒ `14 <./src/p0014.cpp>`__
- ☒ `15 <./src/p0015.cpp>`__
- ☒ `17 <./src/p0017.cpp>`__
- ☒ `22 <./src/p0022.cpp>`__
- ☒ `34 <./src/p0034.cpp>`__
- ☒ `76 <./src/p0076.cpp>`__
- ☒ `836 <./src/p0836.cpp>`__
102 changes: 102 additions & 0 deletions cplusplus/src/include/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#pragma once
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <direct.h>
#include <windows.h>
#define PATH_SEPARATOR "\\"
#else
#include <libgen.h>
#include <unistd.h>
#define PATH_SEPARATOR "/"
#endif

char* get_parent_directory(char* path, const unsigned int levels) {
#ifdef _WIN32
static char drive[_MAX_DRIVE];
static char dir[_MAX_DIR];
_splitpath(path, drive, dir, NULL, NULL);
for (unsigned int i = 0; i < levels; ++i) {
size_t len = strlen(dir);
if (len > 1 && (dir[len - 1] == '\\' || dir[len - 1] == '/')) {
dir[len - 1] = '\0';
}
char* last_slash = strrchr(dir, '\\');
if (!last_slash) last_slash = strrchr(dir, '/');
if (last_slash) *last_slash = '\0';
}
static char parent_dir[_MAX_PATH];
snprintf(parent_dir, sizeof(parent_dir), "%s%s", drive, dir);
return parent_dir;
#else
char* dir = dirname(path);
for (unsigned int i = 0; i < levels; ++i) {
dir = dirname(dir);
if (strcmp(dir, "/") == 0 || strcmp(dir, ".") == 0) {
break;
}
}
return dir;
#endif
}

std::string get_data_file(const char *name) {
const char* start = __FILE__;
#ifdef _WIN32
char absolute_path[MAX_PATH];
if (!_fullpath(absolute_path, start, MAX_PATH)) {
perror("_fullpath");
return NULL;
}
#else
char* absolute_path = realpath(start, NULL);
if (!absolute_path) {
perror("realpath");
return NULL;
}
#endif
char* parents_dir = get_parent_directory(absolute_path, 3);
const size_t p_len = strlen(parents_dir),
name_len = strlen(name);
char *file_path = (char *)malloc(p_len + name_len + 8);
memcpy(file_path, parents_dir, p_len);
memcpy(file_path + p_len, PATH_SEPARATOR "_data" PATH_SEPARATOR, 7);
memcpy(file_path + p_len + 7, name, name_len);
file_path[p_len + name_len + 7] = 0;
FILE* file = fopen(file_path, "r");
#ifndef _WIN32
free(absolute_path);
#endif
// free(parents_dir);
free(file_path);
if (!file) {
perror("fopen");
return NULL;
}

fseek(file, 0, SEEK_END);
size_t length = ftell(file);
fseek(file, 0, SEEK_SET);

char* buffer = (char*)malloc(length + 1);
if (!buffer) {
perror("malloc");
fclose(file);
return NULL;
}

const size_t ret_code = fread(buffer, 1, length, file);
if (ret_code != length) {
if (feof(file))
printf("Error reading %s: unexpected end of file, read %llu of %llu bytes expected\n", name, (unsigned long long)ret_code, (unsigned long long)length);
else if (ferror(file))
perror("Error reading data file");
}

buffer[length] = 0;
fclose(file);

std::string ret(buffer);
free(buffer);
return ret;
}
53 changes: 53 additions & 0 deletions cplusplus/src/p0022.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* Project Euler Problem 22
*
* I know that this could be done faster with a traditional for loop, but I wanted
* to see if iterators were reasonably possible in C, since it makes the prime
* number infrastructure a lot easier to set up.
*
* Problem:
*
* If we list all the natural numbers below 10 that are multiples of 3 or 5, we
* get 3, 5, 6 and 9. The sum of these multiples is 23.
*
* Find the sum of all the multiples of 3 or 5 below 1000.
*/
#ifndef EULER_P0022
#define EULER_P0022
#include <iostream>
#include <vector>
#include <algorithm>
#include "include/utils.h"

unsigned long long p0022() {
unsigned long long answer = 0;
std::string fstring = get_data_file("p0022_names.txt");
const unsigned int name_count = 5163;
std::vector<std::string> names(5163, "");
size_t idx = 0, i = 0, pi = 0;
do {
while (fstring[i] && fstring[i] != ',')
i++;
const size_t len = i - pi - 2;
names[idx] = fstring.substr(pi + 1, len);
idx++;
pi = ++i;
} while (fstring[i]);
std::sort(names.begin(), names.end());
for (idx = 0; idx < name_count; idx++) {
unsigned long score = 0;
for (i = 0; names[idx][i]; i++) {
score += names[idx][i] & 0x3F;
}
answer += score * (idx + 1);
}
return answer;
}

#ifndef UNITY_END
int main(int argc, char const *argv[]) {
std::cout << p0022() << std::endl;
return 0;
}
#endif
#endif
2 changes: 2 additions & 0 deletions cplusplus/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "src/p0015.cpp"
// #include "src/p0016.cpp"
#include "src/p0017.cpp"
#include "src/p0022.cpp"
#include "src/p0034.cpp"
#include "src/p0076.cpp"
#include "src/p0836.cpp"
Expand Down Expand Up @@ -45,6 +46,7 @@ static const Answer answers[] = {
{15, 137846528820, p0015},
// {16, 1366, p0016},
{17, 21124, p0017},
{22, 871198282, p0022},
{34, 40730, p0034},
{76, 190569291, (unsigned long long (*)()) p0076},
};
Expand Down
1 change: 1 addition & 0 deletions cplusplus/test_euler.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
14: 837799,
15: 137846528820,
17: 21124,
22: 871198282,
34: 40730,
76: 190569291,
836: b"aprilfoolsjoke",
Expand Down
10 changes: 5 additions & 5 deletions docs/cplusplus/p0015.rst
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
C++ Implementation of Problem 15
C++ Implementation of Problem 22
================================

View source code :source:`cplusplus/src/p0015.cpp`
View source code :source:`cplusplus/src/p0022.cpp`

Includes
--------

- `math.h <./math.html>`__
- `utils.h <./utils.html>`__

Solution
--------

.. cpp:function:: unsigned long long p0015()
.. cpp:function:: unsigned long long p0022()

.. cpp:function:: int main(int argc, char const *argv[])

.. note::

This function is only present in the Python test runner, or when compiling as a standalone program.

.. literalinclude:: ../../cplusplus/src/p0015.cpp
.. literalinclude:: ../../cplusplus/src/p0022.cpp
:language: C++
:linenos:
18 changes: 18 additions & 0 deletions docs/cplusplus/utils.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
utils.h
=======

View source code :source:`cplusplus/src/include/utils.h`

.. cpp:namespace-push:: utils
.. cpp:function:: std::string get_data_file(const char *name)

Return a character array containing the whole contents of a file found in _data.

.. cpp:function:: char *get_parent_directory(const char *name, const unsigned int levels)

.. cpp:namespace-pop::

.. literalinclude:: ../../cplusplus/src/include/utils.h
:language: C++
:linenos:
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ Problems Solved
+-----------+------------+------------+------------+------------+------------+------------+
|:prob:`21` | | | | |:py-d:`0021`| |
+-----------+------------+------------+------------+------------+------------+------------+
|:prob:`22` |:c-d:`0022` | |:cs-d:`0022`|:js-d:`0022`|:py-d:`0022`|:rs-d:`0022`|
|:prob:`22` |:c-d:`0022` |:cp-d:`0022`|:cs-d:`0022`|:js-d:`0022`|:py-d:`0022`|:rs-d:`0022`|
+-----------+------------+------------+------------+------------+------------+------------+
|:prob:`23` | | | | |:py-d:`0023`| |
+-----------+------------+------------+------------+------------+------------+------------+
Expand Down

0 comments on commit db41f27

Please sign in to comment.