Compare commits

...

48 Commits

Author SHA1 Message Date
hugogogo
4969be8a0d add correction html file 2026-06-05 15:05:53 +02:00
hugogogo
1962b87895 fix X and reduced form 2026-06-05 12:14:21 +02:00
hugogogo
3732c0b777 add debugger 2026-06-05 12:14:04 +02:00
hugogogo
2393c1eea4 update libft 2026-06-05 12:13:20 +02:00
hugogogo
858d4f3ac8 add protection agains big vla 2026-05-26 15:25:41 +02:00
hugogogo
487191c516 add max component 2026-05-26 15:14:28 +02:00
hugogogo
abc5754bba improve parser exponent and detect too big exponent 2026-05-26 14:30:28 +02:00
hugogogo
c99bdfc63a fix number tokens and limits 2026-05-26 12:48:36 +02:00
hugogogo
f1a6a8e586 change output to use discriminant instead of radicant 2026-05-15 02:51:42 +02:00
hugogogo
2824414f53 add positiv_zero in output 2026-05-15 02:45:55 +02:00
hugogogo
0603050d30 fix atoi_supescript 2026-05-15 02:30:13 +02:00
hugogogo
f25291f12f fix complex sign operation 2026-05-15 02:18:50 +02:00
hugogogo
b185647d2b fix reducer sign error 2026-05-15 01:03:14 +02:00
hugogogo
7e16bb5b6f fix printer reduced form order 2026-05-15 00:16:35 +02:00
hugogogo
aa78af4e0f pure quadratic is working 2026-05-14 23:43:58 +02:00
hugogogo
6c6accc289 add logic for pure quadratics 2026-05-14 23:11:37 +02:00
hugogogo
840f5bcfdf improve tests flags 2026-05-14 21:33:44 +02:00
hugogogo
31469af23f add is_nearly_equal_zero 2026-05-14 13:56:44 +02:00
hugogogo
201f2fa0ce add test for equal 2026-05-14 13:42:25 +02:00
hugogogo
7b5aa97c0c improve tester 2026-05-14 13:24:53 +02:00
hugogogo
3761adcf11 fix coefficient sign error 2026-05-14 12:42:57 +02:00
hugogogo
bbe0d65b1f add gcd if all int 2026-05-14 12:31:32 +02:00
hugogogo
d770d7fc87 add tester 2026-05-14 02:13:58 +02:00
hugogogo
00f380f5df fix null coefficient skipped 2026-05-14 00:08:13 +02:00
hugogogo
7978f0d706 improve printer 2026-05-13 23:27:50 +02:00
hugogogo
b0e6483a68 rename executable computor 2026-05-13 22:25:18 +02:00
hugogogo
a91ad5461f update libft 2026-05-12 00:40:01 +02:00
hugogogo
37d9fa2f24 complex solutions 2026-05-11 22:36:55 +02:00
hugogogo
6d2e7922bc wip output and solution 2026-05-10 21:46:37 +02:00
hugogogo
500b6fd932 wip exo ouput 2026-05-10 20:19:24 +02:00
hugogogo
cd6e2327e9 solve all terms 2026-05-10 18:27:34 +02:00
hugogogo
647c9a54b1 wip improve printer 2026-05-10 02:17:25 +02:00
hugogogo
8445604656 improve error solver output 2026-05-10 02:09:41 +02:00
hugogogo
5077db3bc6 fix modf error 2026-05-10 01:51:35 +02:00
hugogogo
ca99f43fe4 update readme with sqrt explication 2026-05-09 14:45:19 +02:00
hugogogo
43b4def6ce wip implemented new union for solve 2026-05-08 01:00:03 +02:00
hugogogo
0fcfd0260d print degree ok 2026-05-07 19:45:42 +02:00
hugogogo
23c788d0c2 new struct for polynom 2026-05-07 19:38:43 +02:00
hugogogo
f62a6fe94f fix output beautify error 2026-05-07 16:05:00 +02:00
hugogogo
09701f8884 fix superscript 1 2026-05-07 14:29:48 +02:00
hugogogo
f373fef4ac wip print before solution 2026-05-07 13:18:28 +02:00
hugogogo
8c22b98d88 solver first part 2026-05-07 00:59:02 +02:00
hugogogo
4c13d21e1f init solver 2026-05-06 22:34:16 +02:00
hugogogo
16c57c9bea handle superscript powers 2026-05-06 20:02:56 +02:00
hugogogo
4b6ad34720 update file structure 2026-05-06 17:51:07 +02:00
hugogogo
0046409c89 basic struct for loop run 2026-05-06 17:39:47 +02:00
hugogogo
93647b56b5 better flag handling 2026-05-06 16:50:05 +02:00
hugogogo
8a479c3c3b simplified error output 2026-05-06 16:17:34 +02:00
24 changed files with 3325 additions and 817 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,4 @@
computorv1
computor
# ---> C
# Prerequisites

55
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,55 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/computor",
// "program": "${workspaceFolder}/sqrt_test",
// "args": ["-5.6x³ + 0x² - 6x + 5"],
// "args": ["x^2 = 0"],
// "args": ["1234567899999x = 1234567899992787676832"],
"args": ["1.5x² + 3.7x + 2.4 = 0"],
// "args": ["x^2 = 0"],
// "args": ["1x² + 2x + 5 = 0"],
// "args": ["0x² + 1x + 5"],
// "args": ["5 * X^0 + 4 * X^1 = 4 * X^0"],
// "args": ["1 * X^0 + 2 * X^1 + 5 * X^2 = 0"],
// "args": ["4 * X^0 + 4 * X^1 = 6 * X^1"],
// "args": ["4 * X^0 - 2 * X^1 = 0"],
// "args": ["1 * X^0 + 5.2 * X^1 = 4.3 * X^1"],
// "args": ["10 * X^0 + 1*x^1 = 15 * X^0 + 1*x^1"],
// "args": ["5 * X^0 + 4 * X^1 - 9.3 * X^2 = 1 * X^0"],
// "args": ["5 * X^0 + 4 * X^1 - 9.3 * X^2 = 5 * X^0 + 22 * X^1 - 9.4 * X^2"],
// "args": [],
// "args": [""],
// "args": ["4"],
// "args": ["1 + 2x + 5x^2"],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
"preLaunchTask": "make"
}
]
}

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"window.title": "${rootName} — ${activeEditorShort}"
}

23
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,23 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc build active file",
"command": "/usr/bin/gcc",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": ["$gcc"],
"group": "build",
"detail": "compiler: /usr/bin/gcc"
}
]
}

View File

@@ -31,24 +31,31 @@ RESET = "\e[0m"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# FILES :
NAME = computorv1
NAME = computor
D_LIB = ./libft
D_HEADERS = ./headers
HEADERS = computorv1.h
D_SRCS = ./src \
./src/utils
SRCS = computorv1.c \
SRCS = main.c \
launcher.c \
lexer.c \
parser.c \
reduce.c \
reducer.c \
solver.c \
errors.c \
print_enums.c
math.c \
printer_equation.c \
printer_solutions.c \
print_enums.c \
print_debug.c
# COMPILATION CONFIG :
CC = gcc
EXT = c
CFLAGS = -Wall -Wextra -Werror $(INCLUDES) -g3
CFLAGS = -Wall -Wextra -Werror $(INCLUDES) -g
LFLAGS = -L$(D_LIB) -lft
LFLAGS += -lm
# AUTOMATICALLY CREATED :
D_OBJS = builds
@@ -96,16 +103,12 @@ $(NAME): $(OBJS)
$(CC) $(OBJS) -o $@ $(LFLAGS)
run: $(NAME)
@echo $(BLUE)"\n -> run \n"$(RESET)
./$(NAME) -d "3.4 * x^2 + 1 * x^1 - 2.0 * x^0 = 5.123 * x^1"
@echo $(BLUE)"\n -> run \n"$(RESET)
./$(NAME) -d "3 * x^2 + 5 * x^1 - 2 * x^0 = 5 * x^1"
@echo $(BLUE)"\n -> run \n"$(RESET)
./$(NAME) -d "3*x^2 + 2*x = 0"
@echo $(BLUE)"\n -> run \n"$(RESET)
./$(NAME) -d "3*x^2 + 2*x -7x^3 = x^3"
@echo $(BLUE)"\n -> run \n"$(RESET)
./$(NAME) -d "3*x^2 + 2*x -7x^4 = x^4"
@echo $(B_PURPLE)"\n---------------------------------------------\nlaunch tests in read-only\n"$(RESET)
-@bash tester.sh --run-only -b
test: $(NAME)
@echo $(B_PURPLE)"\n---------------------------------------------\nlaunch tests\n"$(RESET)
-@bash tester.sh
clean:
$(RM_OBJS)

186
README.md
View File

@@ -1,5 +1,16 @@
# 42_EXT_05_computorv1
## todo
- [ ] arg limit ?
- [x] change order is_number_int and is_number_double
- [x] remove double limit in lexer
- [ ] check why number stored in int or double
- [x] get rid of lib math (check in libft)
- [x] use ft_abs() instead of abs() -> actually abs() is in stdlib
- [x] solve expressions without '=' ?
- [x] solve when max exponent is 0
- [x] check reduced form in subject
## ressources
@@ -13,35 +24,148 @@ this project uses submodules (maybe recursively), so either :
- `git clone --recurse-submodules <repo-url>`
- or, after cloning : `git submodule update --init --recursive`
## steps
---
1. lexer
-> tokens types :
- TOKEN_VARIABLE // x, y, etc.
- TOKEN_NUMBER_INT // int
- TOKEN_NUMBER_DOUBLE // double
- TOKEN_POWER // ^ or **
- TOKEN_SIGN_PLUS // +
- TOKEN_SIGN_MINUS // -
- TOKEN_FACTOR_MULT // *
- TOKEN_FACTOR_DIV // / or :
- TOKEN_EQUAL // =
- END // null
2. parser
-> terms :
- POSITION // left or righ from =
- SIGN // + or -
- COEFFICIENT // double
- EXPONENT // double
3. reduce
-> polynom :
- 0
- 1
- 2
- 3
- ...
4. print reduced form
5. find degree
6. print degree
7. solve
8. print solution
# sqrt implementation
finding the square root of x
## dichotomy method
the dichotomie method, or binary search, consist on dividing the range of research by 2 each time, and choosing the right one for the next iteration.
Ex :
```
solution
|------------------------------ 1. define range bound_1 : 0
|-----------------------------| 2. define range bound_2 : x
|--------------+--------------| 3. take mid : (bound_1 + bound_2) / 2
|--------------|-------ø------| 4. choose range bound : bound_1 or bound_2
---------------|--------------- 1. range bound_1 = mid
|--------------|--------------- 2. range bound_2 = chosen previous bound
|------+-------|--------------- 3. mid
|--ø---|-------|--------------- 4. choose range
-------|----------------------- 1. range bound_1 = mid
-------|-------|--------------- 2. range bound_2 = chosen previous bound
-------|---+---|--------------- 3. mid
-------|---|-ø-|--------------- 4. choose range
-----------|------------------- 1. range bound_1 = mid
-------|---|------------------- 2. range bound_2 = chosen previous bound
-------|-+-|------------------- 3. mid
-------|-|ø|------------------- 4. choose range
---------|--------------------- 1. range bound_1 = mid
-------|-|--------------------- 2. range bound_2 = chosen previous bound
-------|+|--------------------- 3. mid
-------ø|---------------------- 4. choose range
--------|---------------------- --> solution
```
## NewtonRaphson method
it's like a self-correcting binary search, we get rid of the step "choose range", we use the formulae `x/v` to find the next range, with `x` being the number we are trying to get the sqaure root from, and `v` the value found at the previous step.
Ex :
```
solution
------------------------------| 1. define range bound_1 : v
--|---------------------------| 2. choose range bound_2 : x/v
--|-------------+-------------| 3. take mid : (v + x/v) / 2
----------------|-------------- 1. range bound_1 : v = mid
------|---------|-------------- 2. range bound_2 : x/v
------|----+----|-------------- 3. mid
-----------|------------------- 1. range bound_1 : v = mid
-|---------|------------------- 2. range bound_2 : x/v
-|----+----|------------------- 3. mid
------|------------------------ 1. range bound_1 : v = mid
------|-------|---------------- 2. range bound_2 : x/v
------|---+---|---------------- 3. mid
----------|-------------------- 1. range bound_1 : v = mid
------|---|-------------------- 2. range bound_2 : x/v
------|-+-|-------------------- 3. mid
--------|---------------------- --> solution
```
### mathematical proof that each range is automatically in the right range :
- if the value was higher than the answer, then new value is below old value, and vice versa
- how ? :
- define `x`, solution `s = √x`, and value `v = (old_value + x / old_value) / 2`
- supposition : if `v < s` , then `new_v > v`, else `new_v < v` :
- demonstration :
1. if `v < s` :
v < s
<=> v < √x
<=> v² < x (that's actually how we know that v < s)
<=> v²/v < x/v
<=> v < x/v
-> and is s < x/v ? :
v < s
<=> v < √x
<=> v² < x (as previously)
<=> v² < x²/x
<=> v² _ x < x²
<=> (v _ √x)² < x²
<=> v _ √x < x
<=> v _ √x < v \* x/v
<=> √x < x/v
-> so indeed : if v < √x, then v < √x < x/v == v < s < x/v
-> conclusion, the new range < v , x/v > contains the solution
2. the same demonstration works for `v > s`
### here is a more intuitive demonstration, with x = 20 :
1. **show that if `v² > x` (== `v > s`) then `v > s > x/v`, and if `v² < x` (== `v < s`) then `v < s < x/v` :**
1.1. **for value too high `v > s` :**
1.1.1 **why `v > x/v` :** - let's take initial value v = 5 : - is 5² the solution ? 5² == 25 -> so no, 5 is not the sqrt, it's too high
` v v²
0 (5) 10 15 20 25
v : |----|----|----|----|----|
x/v: |---|---|---|---|---| <----- squiz it, so the previous 5 portions fit the x = 20 size
0 (4) 8 12 16 20
x/v x` - the value of the new portion is 4, and we can visually see that it's lower than the previous portion 5 - so : `v > x/v`
1.1.2 **why `s > x/v` :** - let's take the value v = 5 : - we already showed that it's too high, now we will see that x/v == 20/5 is too low :
` v
0 (5) 10 15 20 25
v : |----|----|----|----|----|
x/v: |---|---|---|---|---| <----- squizz
0 *1 *2 *3 *4 *5 -> number of portions
01234 -> portion size
(x/v)²: |---|---|---|---|
0 4 8 12 16` - the portion size is smaller than the number of portions, so it's too small to be the sqrt, indeed we visually see that this portion size `x/v` is a root of a smaller number : `(x/v)² == 16` - so : `s > x/v`
1.1.3. **conclusion :** - v > s - and v > x/v (<- this proof is not essential) - and s > x/v (<- we actually only need this proof) - so `v > s > x/v`
1.2. **for value too high `v < s` :**
- this is the same demonstration but in other direction, let's just summarize it :
- let's take initial value v = 4 :
```
v v²
0 (4) 8 12 16
(1) v : |---|---|---|---|
(2) x/v: |----|----|----|----| -----> stretch
(3) 0 (5) 10 15 20
x/v x
(4) 0 *1 *2 *3 *4 -> number of portions
012345 -> portion size
(5) (x/v)²: |----|----|----|----|----|
0 5 10 15 20 25
```
- (1) : 4 is not the sqrt of x == 20, it's too smalle : (4² == 16) < 20
- (2) : stretch it, so the previous 4 portions fit the x = 20 size
- (3) : the new portion x/v == 5, is more than v == 4, so `v < x/v`
- (4) : portion size is bigger than number of portions, so it's too big to be the root
- (5) : indeed, we see that the portion² == (x/v)² is bigger than x, so √x < x/v == `s < x/v`
- so `v < s < x/v`

View File

@@ -0,0 +1,754 @@
<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta content="IE=Edge,chrome=1" http-equiv="X-UA-Compatible">
<meta content="width=device-width,height=device-height,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0" name="viewport">
<meta content="yes" name="mobile-web-app-capable">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="translucent-black" name="apple-mobile-web-app-status-bar-style">
<meta content="Intranet 42" name="apple-mobile-web-app-title">
<meta content="on" http-equiv="cleartype">
<link href="https://cdn.intra.42.fr/" rel="preconnect">
<link href="https://projects.intra.42.fr/assets/42_logo_black-684989d43d629b3c0ff6fd7e1157ee04db9bb7a73fba8ec4e01543d650a1c607.png" rel="icon" type="image/png">
<link href="https://projects.intra.42.fr/assets/42_logo_black-684989d43d629b3c0ff6fd7e1157ee04db9bb7a73fba8ec4e01543d650a1c607.png" rel="shortcut icon" type="image/png">
<link href="https://projects.intra.42.fr/opensearch.xml" rel="search" title="project" type="application/opensearchdescription+xml">
<title>Intra Projects computorv1 Edit</title>
<meta name="csrf-param" content="authenticity_token">
<meta name="csrf-token" content="rxJbtf6Kj5HEQleDrxloOlvMsOiCU/UjjARaUmhaz/SS1Dv3i3fGF+QSTUbn76n8i+uLffGmJhPxHT7ybO1hMw==">
<link rel="stylesheet" media="all" href="Intra%20Projects%20computorv1%20Edit_files/application-f52eee43c6567eb789b2bc4cf8b30af6103bd129fea7e6d2.css">
<link rel="stylesheet" media="screen" href="Intra%20Projects%20computorv1%20Edit_files/bzd7hlb.css">
<style>
.deprecated {
-webkit-filter: grayscale(100%);
filter: grayscale(100%); }
</style>
<script>
(function() {
this._user = {
"login": "fleitz",
"id": 97542,
"url": "https://profile.intra.42.fr/users/fleitz"
};
this._consumer_address = 'wss://profile.intra.42.fr/cable';
}).call(this);
</script>
<script>
(function() {
this._environment = "production";
this._git_commit = "";
this._release = this._git_commit;
}).call(this);
</script>
<style>@keyframes _spin_evhv6_1{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes _wave_evhv6_1{0%{transform:rotate(0)}50%{transform:rotate(20deg)}to{transform:rotate(0)}}@keyframes _heartBeat_evhv6_1{0%{transform:scale(1)}50%{transform:scale(1.08)}to{transform:scale(1)}}@keyframes _flash_evhv6_1{0%,50%,to{opacity:1}25%,75%{opacity:.2}}@keyframes _bounce_evhv6_1{0%,20%,53%,to{transform:translate(0,0)}40%,43%{transform:translateY(-30px)scaleY(1.1)}70%{transform:translateY(-15px)scaleY(1.05)}80%{transform:translate(0,0)scaleY(.95)}90%{transform:translateY(-4px)scaleY(1.02)}}@keyframes _rubberBand_evhv6_1{0%{transform:scale(1)}30%{transform:scale(1.25,.75)}40%{transform:scale(.75,1.25)}50%{transform:scale(1.15,.85)}65%{transform:scale(.95,1.05)}75%{transform:scale(1.05,.95)}to{transform:scale(1)}}@keyframes _headShake_evhv6_1{0%{transform:translate(0)}6.5%{transform:translate(-6px)rotateY(-9deg)}18.5%{transform:translate(5px)rotateY(7deg)}31.5%{transform:translate(-3px)rotateY(-5deg)}43.5%{transform:translate(2px)rotateY(3deg)}50%{transform:translate(0)}}@keyframes _tada_evhv6_1{0%{transform:scale(1)}10%,20%{transform:scale3d(.9,.9,.9)rotate(-3deg)}30%,50%,70%,90%{transform:scale3d(1.1,1.1,1.1)rotate(3deg)}40%,60%,80%{transform:scale3d(1.1,1.1,1.1)rotate(-3deg)}to{transform:scale(1)}}._overlay_evhv6_157{z-index:1000000006;background-color:#0f0f0f99;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}._layoutDefault_evhv6_170{z-index:2147483000;opacity:0;background-color:#0000;border-radius:5px;width:auto;max-width:95vw;height:auto;display:flex;position:fixed;bottom:20px;right:20px;box-shadow:0 0 0 1px #0f0f0f0d,0 3px 6px #0f0f0f1a,0 9px 24px #0f0f0f33}._layoutModal_evhv6_186{z-index:2147483000;opacity:0;background-color:#0000;border-radius:5px;width:700px;max-width:95vw;height:auto;display:flex;position:relative;box-shadow:0 0 0 1px #0f0f0f0d,0 3px 6px #0f0f0f1a,0 9px 24px #0f0f0f33}._popupContainer_evhv6_200{border-radius:5px;width:100%;display:flex;overflow-y:auto}._popupContainer_evhv6_200 iframe{border-radius:5px;max-height:95vh}._loadingIndicator_evhv6_212{z-index:2147483000;color:#444;background-color:#f5f5f5;border-radius:50%;justify-content:center;align-items:center;width:50px;height:50px;display:inline-flex;position:absolute}._loadingIndicatorNoOverlay_evhv6_225{position:fixed;bottom:10px;right:10px}._loadingIndicator_evhv6_212 svg{width:20px;height:20px;animation:1.618s linear infinite _spin_evhv6_1}._emoji_evhv6_237{font-size:42px;line-height:1;display:inline-block;position:absolute;top:-21px;left:-21px}._animate__wave_evhv6_246{animation:1s ease-in-out 20 _wave_evhv6_1}._animate__heart-beat_evhv6_250{animation:1.3s ease-in-out 20 _heartBeat_evhv6_1}._animate__flash_evhv6_254{animation:2.5s 20 _flash_evhv6_1}._animate__bounce_evhv6_258{transform-origin:bottom;animation:1.5s 20 _bounce_evhv6_1}._animate__rubber-band_evhv6_263{animation:1.5s 20 _rubberBand_evhv6_1}._animate__head-shake_evhv6_267{animation:1.5s ease-in-out 20 _headShake_evhv6_1}._animate__tada_evhv6_271{animation:1.5s 20 _tada_evhv6_1}._animate__spin_evhv6_275{animation:1.618s linear 20 _spin_evhv6_1}@media (height<=1000px){._popupContainer_evhv6_200 iframe{max-height:85vh}}@media (width<=576px){._popupContainer_evhv6_200 iframe{max-height:70vh}._layoutDefault_evhv6_170,._layoutModal_evhv6_186{max-width:calc(100% - 40px)}}
/*$vite$:1*/</style></head><body class=" ">
<div class="notifications-flash-top-bar">
</div>
<script src="Intra%20Projects%20computorv1%20Edit_files/embed.js"></script>
<script>
(function() {
this._notifCount = 0;
this._flashes = [];
}).call(this);
</script>
<div class="notifications-container hidden-xs" data-flashes-url="https://profile.intra.42.fr/flashes" data-notifications-url="https://profile.intra.42.fr/notifications" style="top: 60px; left: 352.3px;">
<header class="notifications--header">
<span>notifications</span>
<a href="https://profile.intra.42.fr/notifications">See all notifications</a>
</header>
<ul class="menu-drop-list"></ul>
</div>
<div class="main-navbar">
<div class="main-navbar-left">
<div class="main-navbar-logo" data-turbolinks-scaffold="">
<a href="https://profile.intra.42.fr/"><img alt="42" src="Intra%20Projects%20computorv1%20Edit_files/42_logo-7dfc9110a5319a308863b96bda33cea995046d1731cebb735e41.svg">
</a></div>
<span class="hidden-sidebars main-menu-trigger lines-button x" data-trigger-menu="">
<span class="fal fa-bars"></span>
</span>
<a class="search-mobile-button hidden-sidebars fal fa-search" href="https://profile.intra.42.fr/searches"></a>
<form action="https://profile.intra.42.fr/searches/search" class="main-navbar-search hidden-xs js-search" data-project-url="https://projects.intra.42.fr/" data-user-url="https://profile.intra.42.fr/users/" method="get">
<span class="twitter-typeahead" style="position: relative; display: inline-block;"><input autocomplete="off" autofocus="" class="search-input tt-input" name="query" placeholder="search..." spellcheck="false" dir="auto" style="position: relative; vertical-align: top;" aria-activedescendant="" aria-owns="undefined_listbox" role="combobox" aria-readonly="true" aria-autocomplete="list"><span role="status" aria-live="polite" class="visuallyhidden"></span><pre aria-hidden="true" style="position: absolute; visibility: hidden; white-space: pre; font-family: &quot;futura-pt&quot;, &quot;Helvetica&quot;, &quot;Sans serif&quot;; font-size: 20.8px; font-style: normal; font-variant: normal; font-weight: 400; word-spacing: 0px; letter-spacing: 0px; text-indent: 0px; text-rendering: optimizelegibility; text-transform: none;"></pre><div role="listbox" class="tt-menu" style="position: absolute; top: 100%; left: 0px; z-index: 100; display: none;"><div role="presentation" class="tt-dataset tt-dataset-0"></div><div role="presentation" class="tt-dataset tt-dataset-1"></div></div></span>
</form>
</div>
<div class="main-navbar-user-nav" data-turbolinks-scaffold="">
<div class="user-actions hidden-xs">
<a class="user-action labelable" data-notification-drop="" href="#"><span class="fal fa-bell"></span>
<span class="user-action-count labeled" data-counter-count="0">0</span>
</a></div>
<span class="dropdown">
<a data-toggle="dropdown" href="#">
<span data-login="fleitz">
fleitz
</span>
<div class="user-profile-picture visible-sidebars" style="background-image: url(https://cdn.intra.42.fr/users/78afa4dec5f92cb54a47dd4108b41d05/fleitz.jpg)"></div>
</a>
<ul aria-labelledby="User menu" class="dropdown-menu" role="menu">
<li>
<a href="https://profile.intra.42.fr/slots"><span class="iconf-calendar"></span>
Manage slots
</a></li>
<li>
<a href="https://profile.intra.42.fr/users/fleitz/edit">Settings</a>
</li>
<li>
<a rel="nofollow" data-method="delete" href="https://signin.intra.42.fr/users/sign_out?all=false"><span class="iconf-power-off"></span>
<b>Logout</b>
</a></li>
</ul>
</span>
<div class="nav-separator hidden-xs"></div>
<div class="help-btn-wrapper hidden-xs">
<button class="btn btn-danger">
<a class="text-white help-btn" href="https://meta.intra.42.fr/articles/i-have-a-problem"><span>
Have a problem?
</span>
</a></button>
</div>
</div>
</div>
<div class="page">
<div class="left-sidebar-fix with-main-menu"></div>
<div class="page-sidebar left-main-container page-sidebar-fixed-left under-main-navbar"><ul class="main-left-navbar">
<div class="_">
<li>
<a class="inactive" href="https://profile.intra.42.fr/"><span class="icon-user-2"></span>
<span class="visible-overlay">
Profile
</span>
</a></li>
<li>
<a class="active" href="https://projects.intra.42.fr/"><span class="icon-network-2-1"></span>
<span class="visible-overlay">
Projets
</span>
</a></li>
<li>
<a class="inactive" href="https://elearning.intra.42.fr/"><span class="icon-movie-play-1"></span>
<span class="visible-overlay">
E-learning
</span>
</a></li>
<li>
<a class="inactive" href="https://stackoverflowteams.com/c/42network"><span class="icon-bubble-conversation-5"></span>
<span class="visible-overlay">
Forum
</span>
</a></li>
<li>
<a class="inactive" href="https://companies.intra.42.fr/"><span class="icon-briefcase"></span>
<span class="visible-overlay">
Companies
</span>
</a></li>
<li>
<a class="inactive" href="https://meta.intra.42.fr/"><span class="icon-compass-2"></span>
<span class="visible-overlay">
Meta
</span>
</a></li>
<li>
<a class="inactive" href="https://shop.intra.42.fr/"><span class="icon-shopping-1"></span>
<span class="visible-overlay">
Shop
</span>
</a></li>
</div>
<div class="admin-links">
</div>
</ul><div class="app-sidebar-left">
<div class="marked-title">Menu</div>
<div class="projects-menu-list">
<a class="project-item sidebar-item" href="https://projects.intra.42.fr/"><span class="icon-briefcase project-status-icon"></span>
My projects
</a><a class="project-item sidebar-item" href="https://projects.intra.42.fr/projects/graph"><span class="icon-globe project-status-icon"></span>
Holy Graph
</a><a class="project-item sidebar-item" href="https://projects.intra.42.fr/projects/list"><span class="icon-list-1 project-status-icon"></span>
List projects
</a><a class="project-item sidebar-item" href="https://projects.intra.42.fr/cursus_subscriptions"><span class="icon-list-1 project-status-icon"></span>
Available Cursus
</a></div>
<div class="marked-title">Your projects</div>
<div class="projects-menu-list">
<a class="project-item sidebar-item" href="https://projects.intra.42.fr/projects/work-experience-ii"><span class="icon-box-2 project-status-icon"></span>
Work Experience II
</a></div>
</div></div>
<div class="page-content" data-turbolinks-scaffold="">
<div class="row">
<div class="main-top-menu">
</div>
<div class="container-item scale-team-container">
<div class="row mt-4">
<div class="scale-section-infos col-sm-12 scale-div">
<h3 class="font-weight-bold text-uppercase text-center mt-4 pt-4">
Scale for project
<a href="https://projects.intra.42.fr/projects/42cursus-computorv1">computorv1</a>
</h3>
<h5 class="text-muted text-center">You should evaluate 1 student in this team</h5>
<!-- -------- La liste des personnes du groupe ------- -->
<div class="team-users-list d-flex justify-content-center">
<div class="team-user-item">
<div class="bg-image-item rounded square-s" data-placement="bottom" data-toggle="tooltip" style="background-image: url(https://cdn.intra.42.fr/users/caa719d989ab3dd344c64f2f6529d90b/hulamy.jpg)" title="" data-original-title="hulamy"></div>
<div class="team-user-item-actions">
<div class="team-user-role rounded bprima"></div>
<span class="iconf-star-1 leader-user" data-placement="bottom" data-toggle="tooltip" title="" data-original-title="Team leader"></span>
</div>
</div>
</div>
<small class="full-width text-muted">Git repository</small>
<div class="container-inner-item project-repo pt-0 mt-0">
<div class="input-group">
<input class="repo-url form-control" disabled="disabled" type="text" value="git@vogsphere.42paris.fr:vogsphere/intra-uuid-40301c23-d514-4206-834f-9b37e6eba967-7374630-hulamy">
<span class="copy input-group-addon" data-clipboard-text="git@vogsphere.42paris.fr:vogsphere/intra-uuid-40301c23-d514-4206-834f-9b37e6eba967-7374630-hulamy">
<span class="icon-paste"></span>
</span>
</div>
</div>
<hr>
<div class="p-0 scale-introduction dancer from-down" id="introduction-53317">
<h3 class="font-weight-bold mb-1">Introduction</h3>
<p>
<br>For the smooth running of this evaluation, please respect the following rules<br>- Remain polite, kind, respectful and constructive whatever happens during<br> this conversation. It's a matter of confidence between you and the<br> 42 community.<br><br>- Highlight the possible problems you met with the work you're presented to<br> the person or the group you're grading, and take the time to talk about and<br> discuss those.<br><br>- Accept the fact that the exam subject or required functions might give place<br> to different interpretations. Remain open to your discussion partner's<br> perspective (are they right or wrong ?) and grade them as fairly as possible.<br> 42's teaching methods can make sense only if peer-assessment is<br> seriously made.<br>
</p>
</div>
<div class="p-0 scale-guidelines dancer from-down" id="guidelines-53317">
<h3 class="font-weight-bold mb-1">Guidelines</h3>
<p>
<br>REMEMBER: you must only evaluate what's in the student's repo. You have to make<br>a "git clone" of the repo and evaluate what's in it. If the assessor has not<br>yet made this project, he will have to read the subject in its entirety before<br>starting this evaluation.<br>
</p>
</div>
<hr>
<div class="dancer from-down" id="attachments-53317">
<h3 class="font-weight-bold mb-1">Attachments</h3>
<div class="project-attachments-list">
</div>
<div class="project-attachments-list">
<div class="project-attachment-item">
<h4 class="attachment-name">
<span class="icon-file"></span>
<a target="_blank" href="https://cdn.intra.42.fr/pdf/pdf/184924/en.subject.pdf">subject.pdf</a>
</h4>
</div>
</div>
</div>
</div>
<form class="simple_form form-horizontal" novalidate="novalidate" id="edit_scale_team_9432498" action="/projects/42cursus-computorv1/project_sessions/7140/evaluations/4923/scales/53317/scale_teams/9432498" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="_method" value="patch"><input type="hidden" name="authenticity_token" value="rxJbtf6Kj5HEQleDrxloOlvMsOiCU/UjjARaUmhaz/SS1Dv3i3fGF+QSTUbn76n8i+uLffGmJhPxHT7ybO1hMw=="><div class="scale-section-answers col-sm-12 scale-div">
<section class="scale-section-item dancer from-down" id="section-147951">
<div class="section-header">
<h3 class="font-weight-bold mb-1">Foreword</h3>
<p class="font-italic"></p>
</div>
<h4 class="scale-question-name">Preliminary instructions</h4>
<p class="scale-section-guidelines">
</p><p>First, check the following elements:</p>
<ul>
<li>There is a turn-in (in the git repository)</li>
<li>No cheating. Students must be able to explain their code.</li>
<li>If the program is written in a compilable language, there is a Makefile
with the rules all, re, and clean, at least.</li>
<li>Mathematic libraries are not allowed in this project. They cannot be used
to calculate the delta root or any second degree equation. You should
check which calculation method the student used and whether they master
it.</li>
<li>If one of these elements is not respected, evaluation stops. Use the
accurate flag. Still, you're invited to keep discussing the subject, but
you won't use the grading system.</li>
</ul>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][0][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504929" name="[scale_team][answers_attributes][0][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][0][value]" id="radio_[scale_team][answers_attributes][0]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][0]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][0][value]" id="radio_[scale_team][answers_attributes][0]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][0]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
</section>
<section class="scale-section-item dancer from-down" id="section-147952">
<div class="section-header">
<hr>
<h3 class="font-weight-bold mb-1">First section</h3>
<p class="font-italic">Mandatory part
</p>
</div>
<h4 class="scale-question-name">Presence of a reduced equation</h4>
<p class="scale-section-guidelines">
</p><p>The program takes an equation in account or waits for it on the standard<br>
entry and displays the same equation in its reduced form afterwards. Is<br>
it the right one ?</p>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][1][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504930" name="[scale_team][answers_attributes][1][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][1][value]" id="radio_[scale_team][answers_attributes][1]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][1]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][1][value]" id="radio_[scale_team][answers_attributes][1]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][1]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
<h4 class="scale-question-name">Reduced equation form</h4>
<p class="scale-section-guidelines">
</p><p>The reduced equation shows the factors until the non null last one, only<br>
once, and either side of the equation is null.</p>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][2][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504931" name="[scale_team][answers_attributes][2][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][2][value]" id="radio_[scale_team][answers_attributes][2]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][2]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][2][value]" id="radio_[scale_team][answers_attributes][2]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][2]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
<h4 class="scale-question-name">Entry management</h4>
<p class="scale-section-guidelines">
</p><p>Try several entries that have a correct format but might have been ill<br>
managed (zero or negative or non whole coefficient...). How well does the<br>
program manage them? (no crash, no calculation error, no infinite loop...)<br>
IMPORTANT NOTICE: if the answer is NO to either question, the evaluation<br>
stops.</p>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][3][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504932" name="[scale_team][answers_attributes][3][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][3][value]" id="radio_[scale_team][answers_attributes][3]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][3]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][3][value]" id="radio_[scale_team][answers_attributes][3]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][3]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
<h4 class="scale-question-name">0 degree equation after reduction</h4>
<p class="scale-section-guidelines">
</p><p>Enter a possible equation ("5 * X^0 = 5 * X^0", for instance). Does the<br>
program tell you that any real number is a solution? Enter an impossible<br>
equation ("4 * X^0 = 8 * X^0", for instance)? Does the program tell you<br>
there is no solution?</p>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][4][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504933" name="[scale_team][answers_attributes][4][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][4][value]" id="radio_[scale_team][answers_attributes][4]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][4]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][4][value]" id="radio_[scale_team][answers_attributes][4]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][4]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
<h4 class="scale-question-name">First degree equation after reduction</h4>
<p class="scale-section-guidelines">
</p><p>Enter a fist degree equation ("5 * X^0 = 4 * X^0 + 7 * X^1", for instance).<br>
Does the program show the solution to the equation?</p>
<p>The program is expected to display:</p>
<p>5 = 4 + 7X ⇒ X = 1/7 ≈ 0.142857</p>
<p>(Note: the reduced form may have a different development, <br>
but the final result must remain the same.)</p>
<p>Run several tests.</p>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][5][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504934" name="[scale_team][answers_attributes][5][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][5][value]" id="radio_[scale_team][answers_attributes][5]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][5]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][5][value]" id="radio_[scale_team][answers_attributes][5]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][5]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
<h4 class="scale-question-name">Second degree equation after reduction - Strictly positive discriminant</h4>
<p class="scale-section-guidelines">
</p><p>Enter a second degree equation with a strictly positive discriminant<br>
("5 * X^0 + 13 * X^1 + 3 * X^2 = 1 * X^0 + 1 * X^1", for instance).</p>
<p>Does the program show it has a strictly positive discriminant?</p>
<p>Does it show two solutions?</p>
<p>Are they correct? (here's an example of a possible solution)</p>
<p>X1 = (-12.0 + sqrt(96.0)) / (2 * 3.0)<br>
X1 = -0.36700683813442847</p>
<p>X2 = (-12.0 - sqrt(96.0)) / (2 * 3.0)<br>
X2 = -3.632993161865572</p>
<p>(Note: the reduced form may have a different development, <br>
but the final result must remain the same.)</p>
<p>Run several tests.</p>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][6][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504935" name="[scale_team][answers_attributes][6][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][6][value]" id="radio_[scale_team][answers_attributes][6]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][6]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][6][value]" id="radio_[scale_team][answers_attributes][6]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][6]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
<h4 class="scale-question-name">Second degree equation after reduction - Zero discriminant</h4>
<p class="scale-section-guidelines">
</p><p>Enter a second degree equation with a discriminant equalling O.</p>
<p>("6 * X^0 + 11 * X^1 + 5 * X^2 = 1 * X^0 + 1 * X^1", for instance).</p>
<p>Does the program show it has a 0 discriminant?</p>
<p>Does it show a single solution?</p>
<p>Is it the correct one? (here's an example of a possible solution)</p>
<p>X0 = -10.0 / (2 * 5.0)<br>
X0 = -1.0</p>
<p>Run several tests.</p>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][7][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504936" name="[scale_team][answers_attributes][7][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][7][value]" id="radio_[scale_team][answers_attributes][7]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][7]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][7][value]" id="radio_[scale_team][answers_attributes][7]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][7]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
<h4 class="scale-question-name">Second degree equation after reduction - Strictly negative discriminant</h4>
<p class="scale-section-guidelines">
</p><p>Enter a second degree equation with a strictly negative discriminant<br>
("5 * X^0 + 3 * X^1 + 3 * X^2 = 1 * X^0 + 0 * X^1", for instance).</p>
<p>Does the program show it has a strictly negative discriminant?</p>
<p>Does it show two complex solution?</p>
<p>Are they correct? Run several tests.</p>
<p>The result should of course show like this: α + β*i.</p>
<p>(here's an example of a possible solution)</p>
<p>Discriminant is strictly negative, the two solutions are complex:<br>
real_part: -3.0 / (2 * 3.0)<br>
imag_part: sqrt(39.0 / (2 * 3.0))<br>
-0.5 + 1.0408330009701328 * i<br>
-0.5 - 1.0408330009701328 * i</p>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][8][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504937" name="[scale_team][answers_attributes][8][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][8][value]" id="radio_[scale_team][answers_attributes][8]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][8]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][8][value]" id="radio_[scale_team][answers_attributes][8]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][8]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
<h4 class="scale-question-name">Third or more degree equation after reduction</h4>
<p class="scale-section-guidelines">
</p><p>Enter a third or higher degree equation. The program should refuse to solve<br>
the equation first. If the program solves it, you can give a score and<br>
show respect... as long as it doesn't crash. If the reduced equation happens<br>
to be a second or lower degree equation, the program should be able to<br>
solve it properly.</p>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][9][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504938" name="[scale_team][answers_attributes][9][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][9][value]" id="radio_[scale_team][answers_attributes][9]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][9]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][9][value]" id="radio_[scale_team][answers_attributes][9]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][9]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
</section>
<section class="scale-section-item dancer from-down" id="section-147953">
<div class="section-header">
<hr>
<h3 class="font-weight-bold mb-1">Bonus</h3>
<p class="font-italic">
Bonus part
</p>
</div>
<h4 class="scale-question-name">Managing a free form entry</h4>
<p class="scale-section-guidelines">
</p><p>Can the program manage a free form entry? * A single coefficient ("4") is<br>
considered a factor of X^0. * A single X is considered having a<br>
coefficient 1 an exponent 1. * An absent exponent ("4 * X") is considered<br>
as equalling 1. * An absent coefficient ("X^6") is considered as equalling</p>
<ol>
<li>* Exponents can appear in arbitrary or repeated order.</li>
</ol>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][10][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504939" name="[scale_team][answers_attributes][10][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="btn-group block">
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][10][value]" id="radio_[scale_team][answers_attributes][10]_true" type="radio" value="1">
<label class="btn btn-success checkbox-label light-bg" for="radio_[scale_team][answers_attributes][10]_true">
<span class="icon-check"></span>
Yes
</label>
<input autocomplete="off" class="checkbox-input" name="[scale_team][answers_attributes][10][value]" id="radio_[scale_team][answers_attributes][10]_false" type="radio" value="0" checked="checked">
<label class="btn btn-danger checkbox-label light-bg" for="radio_[scale_team][answers_attributes][10]_false">
<span class="icon-times"></span>
No
</label>
</div>
</div>
<h4 class="scale-question-name">Second bonus</h4>
<p class="scale-section-guidelines">
</p><p>Error management in the entry (vocabulary and syntax).<br>
Displaying results as irreducible fractions if appropriate. Displaying<br>
intermediate steps. Etc...</p>
<p></p>
<div class="scale-question-answers">
<div class="form-group hidden scale_team_answer_id"><div class="col-sm-10"><input class="form-control hidden" name="[scale_team][answers_attributes][11][id]" type="hidden" id="scale_team_answer_id"></div></div>
<div class="form-group hidden scale_team_answer_question_id"><div class="col-sm-10"><input class="form-control hidden" value="504940" name="[scale_team][answers_attributes][11][question_id]" type="hidden" id="scale_team_answer_question_id"></div></div>
<div class="marked-title text-center">Rate it from 0 (failed) through 5 (excellent)</div>
<input autocomplete="off" class="star-range" data-star-range="" max="5" name="[scale_team][answers_attributes][11][value]" step="1" type="range" value="0" style="position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0;"><div class="rangeslider rangeslider--horizontal" id="js-rangeslider-0"><div class="rangeslider__fill" style="width: 20px;"></div><div class="rangeslider__handle" style="left: 0px;"></div></div>
<hr>
</div>
</section>
</div>
<div class="col-sm-12 scale-div pb-4">
<div class="dancer from-down" id="ratings-53317">
<h3 class="font-weight-bold mb-1">Ratings</h3>
<p class="marked-title">Dont forget to check the flag corresponding to the defense</p>
<div class="btn-group block flags-buttons" data-radio-item="flag-small">
<label class="btn btn-default btn-success label_flag_ok on-active positive" for="scale_team_flag_id_1" name="scale_team[flag_id]">
<span class="iconf-check-4"></span>
Ok
</label>
<label class="btn btn-default btn-success label_flag_outstanding_project on-active positive" for="scale_team_flag_id_9" name="scale_team[flag_id]">
<span class="iconf-star-1"></span>
Outstanding project
</label>
</div>
<div class="btn-group block flags-buttons" data-radio-item="flag-small">
<label class="btn btn-danger btn-default label_flag_empty_work negative on-active" for="scale_team_flag_id_2" name="scale_team[flag_id]">
<span class="iconf-iconf-folder-1"></span>
Empty work
</label>
<label class="btn btn-danger btn-default label_flag_no_author_file negative on-active" for="scale_team_flag_id_4" name="scale_team[flag_id]">
<span class="iconf-file-1"></span>
No author file
</label>
<label class="btn btn-danger btn-default label_flag_invalid_compilation negative on-active" for="scale_team_flag_id_5" name="scale_team[flag_id]">
<span class="iconf-skull-2"></span>
Invalid compilation
</label>
<label class="btn btn-danger btn-default label_flag_norme negative on-active" for="scale_team_flag_id_6" name="scale_team[flag_id]">
<span class="iconf-receipt-1"></span>
Norme
</label>
<label class="btn btn-danger btn-default label_flag_cheat negative on-active" for="scale_team_flag_id_7" name="scale_team[flag_id]">
<span class="iconf-layers"></span>
Cheat
</label>
<label class="btn btn-danger btn-default label_flag_crash negative on-active" for="scale_team_flag_id_8" name="scale_team[flag_id]">
<span class="iconf-bomb"></span>
Crash
</label>
<label class="btn btn-danger btn-default label_flag_forbidden_function negative on-active" for="scale_team_flag_id_13" name="scale_team[flag_id]">
<span class="iconf-delete-2"></span>
Forbidden function
</label>
</div>
</div>
</div>
<div class="col-sm-12 scale-div">
<h3 class="font-weight-bold mb-1">Conclusion</h3>
<div class="scale-final-evaluation hidden">
<div class="form-group radio_buttons optional scale_team_flag"><label class="col-sm-2 control-label radio_buttons optional">Flag</label><div class="col-sm-10"><input type="hidden" name="scale_team[flag_id]" value=""><span class="radio"><label for="scale_team_flag_id_1"><input class="radio_buttons optional" type="radio" value="1" checked="checked" name="scale_team[flag_id]" id="scale_team_flag_id_1">Ok</label></span><span class="radio"><label for="scale_team_flag_id_5"><input class="radio_buttons optional" type="radio" value="5" name="scale_team[flag_id]" id="scale_team_flag_id_5">Invalid compilation</label></span><span class="radio"><label for="scale_team_flag_id_6"><input class="radio_buttons optional" type="radio" value="6" name="scale_team[flag_id]" id="scale_team_flag_id_6">Norme</label></span><span class="radio"><label for="scale_team_flag_id_7"><input class="radio_buttons optional" type="radio" value="7" name="scale_team[flag_id]" id="scale_team_flag_id_7">Cheat</label></span><span class="radio"><label for="scale_team_flag_id_8"><input class="radio_buttons optional" type="radio" value="8" name="scale_team[flag_id]" id="scale_team_flag_id_8">Crash</label></span><span class="radio"><label for="scale_team_flag_id_9"><input class="radio_buttons optional" type="radio" value="9" name="scale_team[flag_id]" id="scale_team_flag_id_9">Outstanding project</label></span><span class="radio"><label for="scale_team_flag_id_13"><input class="radio_buttons optional" type="radio" value="13" name="scale_team[flag_id]" id="scale_team_flag_id_13">Forbidden Function</label></span><span class="radio"><label for="scale_team_flag_id_2"><input class="radio_buttons optional" type="radio" value="2" name="scale_team[flag_id]" id="scale_team_flag_id_2">Empty work</label></span><span class="radio"><label for="scale_team_flag_id_4"><input class="radio_buttons optional" type="radio" value="4" name="scale_team[flag_id]" id="scale_team_flag_id_4">No author file</label></span></div></div>
</div>
<div class="scale-final-comments" id="comments-53317">
<p class="marked-title">Leave a comment on this evaluation ( 2048 chars max )</p>
<textarea required="required" label="false" class="text required col-sm-12 mb-4" aria-required="true" name="scale_team[comment]" id="scale_team_comment"></textarea>
</div>
<input id="token" name="token" class="hidden" type="hidden">
</div>
<div class="scale-final-submit">
<input class="btn btn-primary btn-block font-weight-bold" data-disable-with="Finishing evaluation..." name="commit" type="submit" value="Finish evaluation">
</div>
</form>
</div>
</div>
<footer class="legal-mentions text-center text-muted my-4 col-sm-12 flex justify-content-center flex-column flex-sm-row"><a class="text-muted small px-4" href="https://profile.intra.42.fr/legal/terms/33">API General Terms of Use</a><a class="text-muted small px-4" href="https://profile.intra.42.fr/legal/terms/2">Declaration on the use of cookies</a><a class="text-muted small px-4" href="https://profile.intra.42.fr/legal/terms/35">Privacy policy</a><a class="text-muted small px-4" href="https://profile.intra.42.fr/legal/terms/6">General term of use of the site</a><a class="text-muted small px-4" href="https://profile.intra.42.fr/legal/terms/7">Internal Rules</a><a class="text-muted small px-4" href="https://profile.intra.42.fr/legal/terms/1">Terms of use for video surveillance</a><a class="text-muted small px-4" href="https://profile.intra.42.fr/legal/terms/3">Legal notices</a></footer>
</div>
</div>
</div>
<div aria-hidden="true" aria-labelledby="smartModalLabel" class="modal fade" id="smartModal" role="dialog" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button aria-hidden="true" class="close" data-dismiss="modal" type="button">
x
</button>
<h3 id="smartModalLabel">
</h3>
</div>
<div class="modal-body">
<h4 class="note-title"></h4>
</div>
<div class="modal-footer">
<button aria-hidden="true" class="btn" data-dismiss="modal">Cancel</button>
<button class="send btn btn-primary">Send</button>
</div>
</div>
</div>
</div>
<div aria-hidden="true" aria-labelledby="flashModalLabel" class="modal fade" id="flashModal" role="dialog" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button aria-hidden="true" class="close" data-dismiss="modal" type="button">
x
</button>
<h3 id="flashModalLabel"></h3>
</div>
<div class="modal-body">
<h4 class="note-title">Flash modal content (raw)</h4>
</div>
<div class="modal-footer">
<button aria-hidden="true" class="btn btn-block btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div data-cache="true" class="hide"></div>
<script async="" await="" src="Intra%20Projects%20computorv1%20Edit_files/js"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-BJ34XNRJCV');
</script>
<script>
var jsClasses = ["new_message", "topic-reply"];
jsClasses.forEach(function(className) {
Array.prototype.forEach.call(document.getElementsByClassName(className), function (e) {
e.classList.add("js-hidden");
});
});
</script>
<script src="Intra%20Projects%20computorv1%20Edit_files/application-bace54e58473e5dd340e4d592108f86b3ec50868c47142612.js"></script>
</body></html>

View File

@@ -1,44 +1,61 @@
/* computorv1.h */
#ifndef COMPUTORV1_H
#define COMPUTORV1_H
#include "libft.h"
#include <stdio.h> // tmp for printf, for float debug
#include <stdio.h> // for printf
#include <stdarg.h> // for va_list
#include <stdbool.h>
#include <errno.h> // for errno
#include <string.h> // for strerror
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* COMPUTORV1.C
* MACROS
*/
#define DOUBLE_PRECISION 0.00001
// maximum size supported to avoid excessive variable-length stack allocation (VLA),
// which can lead to stack overflows, segmentation faults, and potential denial-of-service (DoS)
#define MAX_VLA_SIZE 1024
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* MAIN.C
*/
typedef enum
{
MODE_ARGV, //
MODE_STDIN, //
MODE_LOOP, //
} e_program_mode;
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* COMPUTORV1.C
*/
void launch_computorv1(char *input);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* LEXER.C
*/
typedef enum
{
TOKEN_END = 0, // null (end of input)
TOKEN_VARIABLE, // x, y, etc.
TOKEN_NUMBER_INT, // int
TOKEN_NUMBER_DOUBLE, // double
TOKEN_NUMBER_INT_SUPER, // superscript int, like '²'
TOKEN_POWER, // ^ or **
TOKEN_SIGN_PLUS, // +
TOKEN_SIGN_MINUS, // -
TOKEN_FACTOR_MULT, // *
TOKEN_FACTOR_DIV, // / or :
TOKEN_EQUAL, // =
TOKEN_END // null (end of input)
} e_token_type;
typedef enum
{
TOKEN_NO_TAG,
TOKEN_NO_TAG = 0,
TOKEN_NUMBER,
TOKEN_SIGN,
TOKEN_FACTOR,
@@ -56,7 +73,7 @@ typedef struct
};
} s_token;
int lexerize(const char *input, s_token *tokens);
void lexerize(const char *input, s_token *tokens);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* PARSER.C
@@ -64,16 +81,16 @@ int lexerize(const char *input, s_token *tokens);
typedef enum
{
TERM_POS_END = 0, // for last term
TERM_LEFT, // a in "a = b"
TERM_RIGHT, // b in "a = b"
TERM_END, // last term
} e_term_position;
typedef enum
{
TERM_PLUS, // +
TERM_MINUS, // -
TERM_NULL, // null -> for the last term
TERM_SIGN_END = 0, // for last term
TERM_PLUS = '+', // +
TERM_MINUS = '-', // -
} e_term_sign;
typedef struct
@@ -84,34 +101,126 @@ typedef struct
int exponent;
} s_term;
int parse(s_token *tokens, s_term *terms, int terms_count_max);
void parse(s_token *tokens, s_term *terms);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* REDUCE.C
*/
void reduce(s_term *terms, double *polynom);
typedef struct
{
e_term_sign sign;
double coefficient;
int exponent;
} s_polynom;
int reduce(s_term *terms, s_polynom *polynom, int max_exponent);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* SOLVE.C
*/
typedef enum
{
DELTA_ZERO = 0,
DELTA_PLUS = 1,
DELTA_MINUS = -1,
} e_delta_sign;
typedef enum
{
RADICAND_ZERO = 0,
RADICAND_PLUS = 1,
RADICAND_MINUS = -1,
} e_radicand_sign;
typedef struct
{
double a; // a in "ax + b"
double b; // b in "ax + b"
double solution; // double (-b / a)
} s_solution_degree_1;
typedef struct
{
double a; // a in "ax² + bx + c"
double b; // b in "ax² + bx + c"
double c; // c in "ax² + bx + c"
double delta; // Δ == b² - 4ac
e_delta_sign delta_sign; // DELTA_PLUS or DELTA_MINUS or DELTA_ZERO
double delta_absolute; // |Δ|
double delta_sqrt; // √|Δ|
double left_term; // double (-b / 2a)
double right_term; // double (√|Δ| / 2a)
bool all_int; // false if any is double : b, a, √|Δ|
int left_term_numerator; // -b / gcd
int left_term_denominator; // 2a / gcd
int right_term_numerator; // √|Δ| / gcd
int right_term_denominator; // 2a / gcd
} s_solution_degree_2;
typedef struct
{
double a; // a in "ax² + c"
double c; // c in "ax² + c"
double radicand; // x² = -c/a
e_radicand_sign radicand_sign; // RADICAND_PLUS or RADICAND_MINUS or RADICAND_ZERO
double radicand_absolute; // |radicand|
double radicand_sqrt; // √|radicand|
double numerator; // |c|
double numerator_sqrt; // √c
bool numerator_sqrt_is_int; // false if √c is a double
double denominator; // |a|
double denominator_sqrt; // √a
bool denominator_sqrt_is_int; // false if √a is a double
} s_solution_degree_2_pure;
typedef struct
{
int degree;
bool is_quadratic_pure;
union
{
s_solution_degree_1 solution_degree_1;
s_solution_degree_2 solution_degree_2;
s_solution_degree_2_pure solution_degree_2_pure;
};
} s_solution;
void solve(const s_polynom *polynom, s_solution *solution);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* PRINTER_EQUATION.C
*/
void print_reduced_form(s_polynom *polynom, int degree);
void print_degree(s_polynom *polynom, int degree);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* PRINTER_SOLUTIONS.C
*/
void print_solution(s_solution *solution);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* UTILS/MATH.C
*/
bool is_nearly_equal(double num, int compare);
bool is_nearly_equal_zero(double num);
const s_polynom *get_term_of_power(const s_polynom *polynom, int power);
double positiv_zero(double num);
bool has_decimal_part(double num);
bool any_has_decimal_part(double *num, size_t len);
int gcd_int(int a, int b);
int reduce_fraction(double *numerator, double *denominator);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* UTILS/ERRORS.C
*/
typedef enum
{
ERROR_BASE = 1, // start at 1 to avoid exit(0) for errors
ARGUMENTS_ERROR,
ERROR_TOKEN_COUNT,
ERROR_UNKNOWN_TOKEN,
ERROR_NUMBER_TOO_BIG,
ERROR_PARSING,
ERROR_TERM_COUNT,
ERROR_TOKEN_POSITION,
ERROR_VAR_DIFF,
ERROR_SENTINEL, // last token not used, only for enum count
} e_program_error;
void print_state();
int stop_errors(e_program_error err, const char *format, ...);
void stop_errors(const char *format, ...);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* UTILS/PRINT_ENUMS.C
@@ -121,6 +230,14 @@ const char *token_type_to_str(e_token_type type);
const char *token_tag_to_str(e_token_tag tag);
const char *term_position_to_str(e_term_position pos);
const char *term_sign_to_str(e_term_sign sign);
const char *delta_sign_to_str(e_delta_sign sign);
const char *radicand_sign_to_str(e_radicand_sign enum_value);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* UTILS/PRINT_DEBUG.C
*/
void print_debug(const char *description, ...);
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* GLOBALS
@@ -129,8 +246,10 @@ const char *term_sign_to_str(e_term_sign sign);
extern char *input_g_err;
extern s_token *tokens_g_err;
extern s_term *terms_g_err;
extern double *polynom_g_err;
extern int polynom_len_g_err;
extern bool debug_mode;
extern s_polynom *polynom_g_err;
extern s_solution *solution_g_err;
extern bool flag_debug_mode;
extern bool flag_loop_mode;
extern bool flag_beautify_mode;
#endif

2
libft

Submodule libft updated: b64ede50af...9ac98cb1f5

View File

@@ -1,290 +0,0 @@
/* computorv1.c */
#include "computorv1.h"
/**
* GLOBALS
*/
bool debug_mode;
char *input_g_err;
s_token *tokens_g_err;
s_term *terms_g_err;
double *polynom_g_err;
int polynom_len_g_err;
/**
* PROGRAM
*/
static void remove_spaces(char *s)
{
char *read = s;
char *write = s;
// copy all non-space chars
while (*read)
{
if (!ft_isspace(*read))
{
*write++ = *read;
}
read++;
}
*write = '\0';
// zero the rest of the buffer
while (write != read)
{
*write++ = '\0';
}
}
static size_t count_any_of(const char *s, const char *set)
{
size_t count = 0;
for (; *s != '\0'; s++)
{
if (ft_strchr(set, *s) != NULL)
{
count++;
}
}
return count;
}
static void tokens_fill_null(s_token *tokens, size_t arg_len)
{
size_t i;
i = 0;
while (i < arg_len)
{
tokens[i].type = TOKEN_END;
tokens[i].tag = TOKEN_NO_TAG;
tokens[i].value_char = '\0';
i++;
}
}
static void terms_fill_null(s_term *terms, size_t terms_count_prediction)
{
size_t i;
i = 0;
while (i < terms_count_prediction)
{
terms[i].coefficient = 0.0;
terms[i].exponent = 0;
terms[i].position = TERM_END;
terms[i].sign = TERM_NULL;
i++;
}
}
static int get_max_exponent(s_term *terms)
{
int i;
int max_exponent;
i = 0;
max_exponent = 0;
while (terms[i].position != TERM_END)
{
if (terms[i].exponent > max_exponent)
{
max_exponent = terms[i].exponent;
}
i++;
}
return max_exponent;
}
static void polynom_fill_null(double *polynom, int len)
{
int i;
i = 0;
while (i < len)
{
polynom[i] = 0.0;
i++;
}
}
static void launch_argv(char *input)
{
int ret;
int max_exponent;
size_t arg_len;
size_t terms_count_prediction;
// init
input_g_err = input;
remove_spaces(input);
// lexerize
arg_len = ft_strlen(input) + 1; // +1 for last END token
// ft_printf("-> tokens[%i]\n", arg_len); // debug
s_token tokens[arg_len];
tokens_g_err = tokens;
tokens_fill_null(tokens, arg_len);
ret = lexerize(input, tokens);
if (ret == 0)
{
stop_errors(ERROR_TOKEN_COUNT, "lexer returned 0 token");
}
// parse
terms_count_prediction = count_any_of(input, "-+=") + 2; // +1 for first term that can have no leading '+', +1 for last term == NULL
// ft_printf("-> terms[%i]\n", terms_count_prediction); // debug
s_term terms[terms_count_prediction];
terms_g_err = terms;
terms_fill_null(terms, terms_count_prediction);
ret = parse(tokens, terms, terms_count_prediction);
if (ret == 0)
{
stop_errors(ERROR_TERM_COUNT, "parser returned 0 term");
}
// reduce
max_exponent = get_max_exponent(terms) + 1;
double polynom[max_exponent];
polynom_g_err = polynom;
polynom_len_g_err = max_exponent;
polynom_fill_null(polynom, max_exponent);
reduce(terms, polynom);
// debug
print_state();
}
// trim spaces and quotes and newlines
static void clean_copy_input(char *input, char *line)
{
size_t i;
size_t j;
size_t len;
size_t len_trim_end;
size_t len_trim_start;
len = ft_strlen(line);
// get len minus : ' | " | \n | <space>
i = len;
while (i > 0)
{
if (ft_strchr("\"\'\n", line[i]))
i--;
if (ft_isspace(line[i]))
i--;
break;
}
len_trim_end = i;
// get len of leading chars : ' | " | <space> | \n
i = 0;
while (i < len_trim_end)
{
if (ft_strchr("\"\'\n", line[i]))
i++;
if (ft_isspace(line[i]))
i++;
break;
}
len_trim_start = i;
// copy into input
i = len_trim_start;
j = 0;
while (i <= len_trim_end)
{
input[j] = line[i];
j++;
i++;
}
input[j] = '\0';
}
static void launch_stdin()
{
char *line;
size_t len;
line = NULL;
len = 0;
// get input
getline(&line, &len, stdin);
// prepare input
char input[len];
clean_copy_input(input, line);
// launch input
launch_argv(input);
// FREE LINE !
free(line);
}
int main(int ac, char **av)
{
char *input;
e_program_mode program_mode;
debug_mode = false;
// check arguments
program_mode = MODE_ARGV;
if (ac > 3)
{
stop_errors(ARGUMENTS_ERROR, "too many arguments");
}
else if (ac == 3)
{
if ((ft_strcmp(av[1], "-d") == 0))
{
debug_mode = true;
input = av[2];
}
else if ((ft_strcmp(av[2], "-d") == 0))
{
debug_mode = true;
input = av[1];
}
else
{
stop_errors(ARGUMENTS_ERROR, "3rd argument is not a valid flag: '%s'", av[2]);
}
}
else if (ac == 2)
{
if ((ft_strcmp(av[1], "-d") == 0))
{
debug_mode = true;
program_mode = MODE_STDIN;
}
else
{
input = av[1];
}
}
else if (ac < 2)
{
program_mode = MODE_STDIN;
}
// launch calculator
if (program_mode == MODE_ARGV)
{
launch_argv(input);
}
else if (program_mode == MODE_STDIN)
{
launch_stdin();
}
return (0);
}

150
src/launcher.c Normal file
View File

@@ -0,0 +1,150 @@
/* launcher.c */
#include "computorv1.h"
static void remove_spaces(char *s)
{
char *read = s;
char *write = s;
// copy all non-space chars
while (*read)
{
if (!ft_isspace(*read))
{
*write++ = *read;
}
read++;
}
*write = '\0';
// zero the rest of the buffer
while (write != read)
{
*write++ = '\0';
}
}
static size_t count_any_of(const char *s, const char *set)
{
size_t count = 0;
for (; *s != '\0'; s++)
{
if (ft_strchr(set, *s) != NULL)
{
count++;
}
}
return count;
}
static int get_max_exponent(s_term *terms)
{
int i;
int max_exponent;
i = 0;
max_exponent = 0;
while (terms[i].position != TERM_POS_END)
{
if (terms[i].exponent > max_exponent)
{
max_exponent = terms[i].exponent;
}
i++;
}
print_debug("-> max_exponent: %i\n\n", max_exponent);
return max_exponent;
}
static int get_number_of_exponents(s_term *terms, int max_exponent)
{
int i;
int nbr_of_exponents;
if (max_exponent < 0 || max_exponent > MAX_VLA_SIZE)
stop_errors("max_exponent should be between 0 and %d, but got : %d\n", MAX_VLA_SIZE, max_exponent);
int exponent_present[max_exponent];
ft_bzero(exponent_present, sizeof(exponent_present));
// mark exponents as present
i = 0;
while (terms[i].position != TERM_POS_END)
{
exponent_present[terms[i].exponent] = 1;
i++;
}
// Count unique exponents
nbr_of_exponents = 0;
i = 0;
while (i < max_exponent)
{
if (exponent_present[i] == 1)
nbr_of_exponents++;
i++;
}
print_debug("-> nbr_of_exponents: %i\n\n", nbr_of_exponents);
return nbr_of_exponents;
}
void launch_computorv1(char *input)
{
int max_exponent;
int nbr_of_exponents;
int degree;
size_t token_len;
size_t terms_count_prediction;
// init
input_g_err = input;
remove_spaces(input);
// lexerize
token_len = ft_strlen(input) + 1; // +1 for last END token
print_debug("\n-> tokens[%i]\n", token_len);
if (token_len <= 0 || token_len > MAX_VLA_SIZE)
stop_errors("token_len should be between 1 and %d, but got : %d\n", MAX_VLA_SIZE, token_len);
s_token tokens[token_len];
tokens_g_err = tokens;
ft_bzero(tokens, sizeof(tokens));
lexerize(input, tokens);
// parse
terms_count_prediction = count_any_of(input, "-+=") + 2; // +1 for first term that can have no leading '+', +1 for last term == NULL
print_debug("-> terms[%i]\n\n", terms_count_prediction);
if (terms_count_prediction <= 0 || terms_count_prediction > MAX_VLA_SIZE)
stop_errors("terms_count_prediction should be between 1 and %d, but got : %d\n", MAX_VLA_SIZE, terms_count_prediction);
s_term terms[terms_count_prediction];
terms_g_err = terms;
ft_bzero(terms, sizeof(terms));
parse(tokens, terms);
// reduce
max_exponent = get_max_exponent(terms);
nbr_of_exponents = get_number_of_exponents(terms, max_exponent);
s_polynom polynom[nbr_of_exponents + 2]; // +1 for last term, +1 for the degree (eg. degree 2 means 3 terms)
polynom_g_err = polynom;
ft_bzero(polynom, sizeof(polynom));
degree = reduce(terms, polynom, max_exponent);
print_debug("-> degree: %i\n\n", degree);
// print before solution
print_reduced_form(polynom, degree);
print_degree(polynom, degree);
// solve
s_solution solution[1];
solution_g_err = solution;
ft_bzero(solution, sizeof(solution));
solution[0].degree = degree;
solve(polynom, solution);
// print solution
print_solution(solution);
// debug
print_state();
}

View File

@@ -2,6 +2,67 @@
#include "computorv1.h"
/**
* INT CHECKS
*/
static bool is_number_bigger_than_int_max(const char *input, int size)
{
const char *int_max_str = "2147483647";
int int_max_len = ft_strlen(int_max_str);
if (size < int_max_len)
return false;
if (size > int_max_len)
return true;
return ft_strncmp(input, int_max_str, int_max_len) > 0;
}
static bool is_number_smaller_than_int_min(const char *input, int size)
{
const char *int_min_str = "-2147483648";
int int_min_len = ft_strlen(int_min_str);
if (size < int_min_len)
return false;
if (size > int_min_len)
return true;
return ft_strncmp(input, int_min_str, int_min_len) < 0;
}
static bool is_number_out_of_int_range(const char *input, int size)
{
if (input[0] == '-')
{
return is_number_smaller_than_int_min(input, size);
}
else
{
return is_number_bigger_than_int_max(input, size);
}
}
/**
* SUPERSCRIPT DIGIT CHECKS
*/
static bool is_superscript_bigger_than_int_max(const char *input, int size)
{
const char *int_max_str = "²¹⁴⁷⁴⁸³⁶⁴⁷";
int int_max_len = ft_strlen(int_max_str);
if (size < int_max_len)
return false;
if (size > int_max_len)
return true;
return ft_strncmp(input, int_max_str, int_max_len) > 0;
}
/**
* TOKEN CHECKS
*/
// token is alphabet letter, like 'x' or 'y'
static bool token_is_variable(const char *input, int input_pos, int *token_size)
{
@@ -17,85 +78,95 @@ static bool token_is_variable(const char *input, int input_pos, int *token_size)
static bool token_is_number_int(const char *input, int input_pos, int *token_size)
{
int number_size;
int max_number_size;
if (!ft_isdigit(input[input_pos]))
{
return false;
}
number_size = 0;
number_size = 1;
max_number_size = 16; // max size for int
while (number_size <= max_number_size)
while (input[input_pos + number_size] != '\0')
{
if (ft_isdigit(input[input_pos + number_size]))
{
number_size++;
}
else if (input[input_pos + number_size] == '.')
else
break;
}
if (number_size == 0)
{
if (ft_isdigit(input[input_pos + number_size + 1]))
{
// number is double
return false;
}
else
break;
}
else
break;
}
if (number_size > max_number_size)
if (is_number_out_of_int_range(&input[input_pos], number_size))
{
stop_errors(ERROR_NUMBER_TOO_BIG, &input[input_pos]);
return false;
}
*token_size = number_size;
return true;
}
// token is double "123.456"
// token is double "123.456" or token < MIN_INT or token > MAX_INT
static bool token_is_number_double(const char *input, int input_pos, int *token_size)
{
int number_size;
int max_number_size;
bool has_dot;
if (!ft_isdigit(input[input_pos]))
{
return false;
}
has_dot = false;
number_size = 1;
max_number_size = 24; // max char needed to represent double : 1 sign + 1 point + 17 fractinoal part + 5 exponent
while (number_size <= max_number_size)
number_size = 0;
while (input[input_pos + number_size] != '\0')
{
if (ft_isdigit(input[input_pos + number_size]))
{
number_size++;
}
else if (input[input_pos + number_size] == '.')
else if (input[input_pos + number_size] == '.' && !has_dot)
{
if (has_dot)
{
// number is not a valid token, it has 2 dots
return false;
}
if (!ft_isdigit(input[input_pos + number_size + 1]))
{
// number is not valid token, it has a dot with no number after the dot
return false;
}
has_dot = true;
number_size++;
}
else
break;
}
if (number_size > max_number_size)
if (is_number_out_of_int_range(&input[input_pos], number_size))
{
stop_errors(ERROR_NUMBER_TOO_BIG, &input[input_pos]);
*token_size = number_size;
return true;
}
if (!has_dot)
{
return false;
}
*token_size = number_size;
return true;
}
// token is superscript int e.g. ¹, ², ³, ⁴, ⁵, ⁶⁶⁶
static bool token_is_number_int_super(const char *input, int input_pos, int *token_size)
{
int digit_size = 0;
int number_size = 0;
// iterate to find full superscript number
while (input[input_pos + number_size] != '\0')
{
if (ft_isdigit_superscript(&input[input_pos + number_size], &digit_size))
{
// Increment by the length of the UTF-8 character (2 or 3 bytes)
number_size += digit_size;
}
else
{
break;
}
}
if (number_size == 0)
{
return false;
}
if (is_superscript_bigger_than_int_max(&input[input_pos], number_size))
{
return false;
}
*token_size = number_size;
return true;
}
@@ -179,12 +250,15 @@ static bool token_is_equal(const char *input, int input_pos, int *token_size)
/**
* LEXER
*/
int lexerize(const char *input, s_token *tokens)
void lexerize(const char *input, s_token *tokens)
{
int tokens_count;
int input_pos;
int token_size;
// bool has_equal;
// has_equal = false;
tokens_count = 0;
input_pos = 0;
while (input[input_pos])
@@ -202,17 +276,23 @@ int lexerize(const char *input, s_token *tokens)
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = 'x';
}
else if (token_is_number_double(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_NUMBER_DOUBLE;
tokens[tokens_count].tag = TOKEN_NUMBER;
tokens[tokens_count].value_double = ft_atof(&input[input_pos]);
}
else if (token_is_number_int(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_NUMBER_INT;
tokens[tokens_count].tag = TOKEN_NUMBER;
tokens[tokens_count].value_int = ft_atoi(&input[input_pos]);
}
else if (token_is_number_double(input, input_pos, &token_size))
else if (token_is_number_int_super(input, input_pos, &token_size))
{
tokens[tokens_count].type = TOKEN_NUMBER_DOUBLE;
tokens[tokens_count].type = TOKEN_NUMBER_INT_SUPER;
tokens[tokens_count].tag = TOKEN_NUMBER;
tokens[tokens_count].value_double = ft_atof(&input[input_pos]);
tokens[tokens_count].value_int = ft_atoi_superscript(&input[input_pos]);
}
else if (token_is_power(input, input_pos, &token_size))
{
@@ -246,26 +326,28 @@ int lexerize(const char *input, s_token *tokens)
}
else if (token_is_equal(input, input_pos, &token_size))
{
// has_equal = true;
tokens[tokens_count].type = TOKEN_EQUAL;
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '=';
}
else
{
stop_errors(ERROR_UNKNOWN_TOKEN, &input[input_pos]);
stop_errors("input[input_pos] is not any token: %s\n", &input[input_pos]);
}
tokens_count++;
if (token_size == 0)
{
stop_errors(ERROR_UNKNOWN_TOKEN, &input[input_pos]);
stop_errors("token_size is 0 : %s\n", &input[input_pos]);
}
input_pos += token_size;
}
// if (!has_equal)
// stop_errors("the input polynomial does not contains an equal sign, it's an expression not an equation.\n");
tokens[tokens_count].type = TOKEN_END;
tokens[tokens_count].tag = TOKEN_NO_TAG;
tokens[tokens_count].value_char = '\0';
return tokens_count;
}

181
src/main.c Normal file
View File

@@ -0,0 +1,181 @@
/* main.c */
#include "computorv1.h"
/**
* GLOBALS
*/
bool flag_debug_mode;
bool flag_loop_mode;
bool flag_beautify_mode;
char *input_g_err;
s_token *tokens_g_err;
s_term *terms_g_err;
s_polynom *polynom_g_err;
s_solution *solution_g_err;
/**
* PROGRAM
*/
static void print_usage()
{
ft_printf("USAGE :\n\n");
ft_printf("| ./computorv1 [flags] [polynom]\n");
ft_printf("| ./computorv1 [polynom] [flags]\n");
ft_printf("| ./computorv1 [flags] -> interactiv mode\n\n");
ft_printf("[flags] :\n");
ft_printf("-d : print debug\n");
ft_printf("-l : interactive loop\n");
ft_printf("-b : beautify output\n");
ft_putchar('\n');
}
// trim spaces and quotes and newlines
static void clean_copy_input(char *input, char *line)
{
size_t i;
size_t j;
size_t len;
size_t len_trim_end;
size_t len_trim_start;
len = ft_strlen(line);
// get len minus : ' | " | \n | <space>
i = len;
while (i > 0)
{
if (ft_strchr("\"\'\n", line[i]))
i--;
if (ft_isspace(line[i]))
i--;
break;
}
len_trim_end = i;
// get len of leading chars : ' | " | <space> | \n
i = 0;
while (i < len_trim_end)
{
if (ft_strchr("\"\'\n", line[i]))
i++;
if (ft_isspace(line[i]))
i++;
break;
}
len_trim_start = i;
// copy into input
i = len_trim_start;
j = 0;
while (i <= len_trim_end)
{
input[j] = line[i];
j++;
i++;
}
input[j] = '\0';
}
static void launch_stdin()
{
char *line;
size_t len;
line = NULL;
len = 0;
// get input
getline(&line, &len, stdin);
// prepare input
char input[len];
clean_copy_input(input, line);
// launch input
launch_computorv1(input);
// FREE LINE !
free(line);
}
// static void launch_stdin_loop()
// {
// while (1)
// {
// // for the moment it does not work since errors exit
// launch_stdin();
// }
// }
int main(int ac, char **av)
{
int i;
char *input;
e_program_mode program_mode;
// init flags
flag_debug_mode = false;
flag_loop_mode = false;
flag_beautify_mode = false;
// check arguments
program_mode = MODE_ARGV;
// get flags
input = NULL;
i = 1;
while (i < ac)
{
if ((ft_strcmp(av[i], "-d") == 0))
{
// flag -d : debug
flag_debug_mode = true;
}
else if ((ft_strcmp(av[i], "-l") == 0))
{
// flag -l : interactiv loop
flag_loop_mode = true;
program_mode = MODE_LOOP;
}
else if ((ft_strcmp(av[i], "-b") == 0))
{
// flag -b : beautify output
flag_beautify_mode = true;
}
else if (ft_strlen(av[i]) == 2 && av[i][0] == '-')
{
// unknown flag
print_usage();
stop_errors("unknwon flag '%s'", av[i]);
}
else
{
input = av[i];
}
i++;
}
// if input was not set, it means interactiv mode
if (input == NULL)
{
program_mode = MODE_STDIN;
}
// launch calculator
if (program_mode == MODE_ARGV)
{
launch_computorv1(input);
}
else if (program_mode == MODE_STDIN)
{
launch_stdin();
}
// else if (program_mode == MODE_LOOP)
// {
// launch_stdin_loop();
// }
return (0);
}

View File

@@ -16,35 +16,51 @@
static e_term_sign get_sign(s_token *tokens, int i, int *token_count)
{
*token_count = 0;
int j;
e_term_sign ret_sign;
// default to '+'
ret_sign = TERM_PLUS;
// sign
if (tokens[i].tag == TOKEN_SIGN)
{
*token_count = 1;
}
else if (i == 0) // if most left term, the sign can be ommited for a '+' sign in front of a number or variable
// we can have two signs in a row, like "3 - -2" or "3 - +2"
j = 0;
while (j < 2)
{
*token_count = 0;
return TERM_PLUS;
if (tokens[i + j].tag != TOKEN_SIGN)
break;
if (tokens[i + j].type == TOKEN_SIGN_MINUS)
ret_sign = (ret_sign == TERM_PLUS) ? TERM_MINUS : TERM_PLUS;
*token_count += 1;
j++;
}
else if (tokens[i - 1].type == TOKEN_EQUAL) // if first token after 'equal', the sign can be ommited for a '+' sign in front of a number or variable
}
else if (i == 0)
{
// if most left term, the sign can be ommited for a '+' sign in front of a number or variable
*token_count = 0;
return TERM_PLUS;
ret_sign = TERM_PLUS;
}
else if (tokens[i - 1].type == TOKEN_EQUAL)
{
// if first token after 'equal', the sign can be ommited for a '+' sign in front of a number or variable
*token_count = 0;
ret_sign = TERM_PLUS;
}
else
{
stop_errors(ERROR_TOKEN_POSITION, "at begining of term, we should have a token 'sign', not '%s' (token[%i])", token_type_to_str(tokens[i].type), i);
stop_errors("at begining of term, we should have a token 'sign', not '%s' (token[%i])", token_type_to_str(tokens[i].type), i);
}
return tokens[i].type == TOKEN_SIGN_PLUS ? TERM_PLUS : TERM_MINUS;
return ret_sign;
}
static double get_double_value(s_token token)
{
if (token.tag != TOKEN_NUMBER)
{
stop_errors(ERROR_UNKNOWN_TOKEN, "this was suppose to be a number, instead got a %s", token_type_to_str(token.type));
stop_errors("this was suppose to be a number, instead got a %s", token_type_to_str(token.type));
}
if (token.type == TOKEN_NUMBER_DOUBLE)
{
@@ -54,7 +70,7 @@ static double get_double_value(s_token token)
return token.value_int;
}
static double get_coefficient_absolute(s_token *tokens, int i, int *token_count)
static double get_coefficient(s_token *tokens, int i, int *token_count)
{
double coefficient;
@@ -100,70 +116,85 @@ static double get_coefficient_absolute(s_token *tokens, int i, int *token_count)
return coefficient;
}
static bool token_sequence(s_token *tokens, e_token_type *types, int len)
{
int i;
i = 0;
while (i < len)
{
if (tokens[i].type != types[i])
return false;
i++;
}
return true;
}
static int get_exponent(s_token *tokens, int i, int *token_count)
{
*token_count = 0;
int ret_exponent;
// valide :
// - '*x^2' -> exponent 2
// - '*x²' -> exponent 2
// - 'x^2' -> exponent 2
// - '*x' -> exponent 1
// - 'x' -> exponent 1
// - [*] [x] [^] [2] -> exponent 2
// - [*] [x] [²] -> exponent 2
// - [*] [x] -> exponent 1
// - [x] [^] [2] -> exponent 2
// - [x] [²] -> exponent 2
// - [x] -> exponent 1
// - '' -> exponent 0
// invalid first token :
// - '2' -> number
// first reach VARIABLE : 'x' or '*x'
if (tokens[i].type == TOKEN_VARIABLE)
if (tokens[i].tag == TOKEN_NUMBER)
{
// token is 'x'
i++;
*token_count = 1;
// exponent term cannot begin with a number
stop_errors("at exponent place, we should have an exponent expression, but instead got : '%s' (token number %i)", token_type_to_str(tokens[i].type), i);
}
else if (tokens[i].type == TOKEN_FACTOR_MULT)
else if (token_sequence(&tokens[i], (e_token_type[]){TOKEN_FACTOR_MULT, TOKEN_VARIABLE, TOKEN_POWER, TOKEN_NUMBER_INT}, 4))
{
// token is '*'
i++;
if (tokens[i].type == TOKEN_VARIABLE)
// ex: [*] [x] [^] [2]
*token_count = 4;
ret_exponent = tokens[i + 3].value_int;
}
else if (token_sequence(&tokens[i], (e_token_type[]){TOKEN_FACTOR_MULT, TOKEN_VARIABLE, TOKEN_NUMBER_INT_SUPER}, 3))
{
// tokens are '*x'
i++;
// ex: [*] [x] [²]
*token_count = 3;
ret_exponent = tokens[i + 2].value_int;
}
else if (token_sequence(&tokens[i], (e_token_type[]){TOKEN_FACTOR_MULT, TOKEN_VARIABLE}, 2))
{
// ex: [*] [x] -> exponent 1
*token_count = 2;
ret_exponent = 1;
}
else if (token_sequence(&tokens[i], (e_token_type[]){TOKEN_VARIABLE, TOKEN_POWER, TOKEN_NUMBER_INT}, 3))
{
// ex: [x] [^] [2]
*token_count = 3;
ret_exponent = tokens[i + 2].value_int;
}
else if (token_sequence(&tokens[i], (e_token_type[]){TOKEN_VARIABLE, TOKEN_NUMBER_INT_SUPER}, 2))
{
// ex: [x] [²]
*token_count = 2;
ret_exponent = tokens[i + 1].value_int;
}
else if (token_sequence(&tokens[i], (e_token_type[]){TOKEN_VARIABLE}, 1))
{
// ex: [x] -> exponent 1
*token_count = 1;
ret_exponent = 1;
}
else
{
stop_errors(ERROR_TOKEN_POSITION, "at exponent place, after a '*' we should have a 'var', but instead got : '%c' (token number %i)", tokens[i].value_char, i);
}
}
else
{
// if token are neither 'x' or '*x', then exponent is 0
return 0;
// no variable, so no exponent -> exponent 0
*token_count = 0;
ret_exponent = 0;
}
// then get power sign '^'
if (tokens[i].type == TOKEN_POWER)
{
i++;
*token_count += 1;
}
// else if (tokens[i].type == TOKEN_NUMBER_INT_POWER){}
else
{
// if token is 'x' not followed by '^' -> it's an exponent 1
return 1;
}
// then get exponent
if (tokens[i].type == TOKEN_NUMBER_INT)
{
*token_count += 1;
}
else
{
stop_errors(ERROR_TOKEN_POSITION, "at exponent place, we should have an int, but instead got : '%c' (token number %i)", tokens[i].value_char, i);
}
return tokens[i].value_int;
return ret_exponent;
}
static void check_variables(s_token *tokens)
@@ -184,14 +215,14 @@ static void check_variables(s_token *tokens)
}
else if (var != tokens[i].value_char)
{
stop_errors(ERROR_VAR_DIFF, "old var : '%c' - new var : '%c' (token number %i)", var, tokens[i].value_char, i);
stop_errors("old var : '%c' - new var : '%c' (token number %i)", var, tokens[i].value_char, i);
}
}
i++;
}
}
int parse(s_token *tokens, s_term *terms, int terms_count_max)
void parse(s_token *tokens, s_term *terms)
{
int i;
int terms_count;
@@ -201,13 +232,15 @@ int parse(s_token *tokens, s_term *terms, int terms_count_max)
check_variables(tokens);
print_debug("PARSER STEPS :\n");
terms_count = 0;
token_count = 0;
i = 0;
term_position = TERM_LEFT;
while (tokens[i].type != TOKEN_END && terms_count < terms_count_max)
while (tokens[i].type != TOKEN_END)
{
// ft_printf("- token[%i]\n", i); // debug
print_debug("- token[%i]\n", i);
// equal
if (tokens[i].type == TOKEN_EQUAL)
@@ -225,39 +258,28 @@ int parse(s_token *tokens, s_term *terms, int terms_count_max)
e_term_sign ret_sign = get_sign(tokens, i, &token_count);
terms[terms_count].sign = ret_sign;
if (ret_sign == TERM_MINUS)
{
sign = -1;
}
i += token_count;
// ft_printf("term[%i] get_sign: (%i)[%s], token_count: [%d]\n", terms_count, ret_sign, term_sign_to_str(ret_sign), token_count); // debug
print_debug("term[%i] get_sign: (%i)[%s], token_count: [%d]\n", terms_count, ret_sign, term_sign_to_str(ret_sign), token_count);
// coefficient
double ret_coefficient = get_coefficient_absolute(tokens, i, &token_count);
double ret_coefficient = get_coefficient(tokens, i, &token_count);
terms[terms_count].coefficient = ret_coefficient * sign;
i += token_count;
// printf("term[%i] get_coefficient: [%g], token_count: [%d]\n", terms_count, ret_coefficient, token_count); // debug
print_debug("term[%i] get_coefficient: [%g], token_count: [%d]\n", terms_count, ret_coefficient, token_count);
// exponent
int ret_exponent = get_exponent(tokens, i, &token_count);
terms[terms_count].exponent = ret_exponent;
i += token_count;
// ft_printf("term[%i] get_exponent: [%i], token_count: [%d]\n", terms_count, ret_exponent, token_count); // debug
print_debug("term[%i] get_exponent: [%i], token_count: [%d]\n", terms_count, ret_exponent, token_count);
terms_count++;
}
// last token is TOKEN_END, and terms[] should have at least one more spot for the END term
if (tokens[i].type == TOKEN_END && terms_count < terms_count_max)
{
terms[terms_count].position = TERM_END;
terms[terms_count].sign = TERM_NULL;
// last token is TOKEN_END
terms[terms_count].position = TERM_POS_END;
terms[terms_count].sign = TERM_SIGN_END;
terms[terms_count].coefficient = 0;
terms[terms_count].exponent = 0;
}
else
{
stop_errors(ERROR_PARSING, "terms_count: %i, terms_count_max: %i, tokens[%i].type: %s", terms_count, terms_count_max, i, token_type_to_str(tokens[i].type));
}
return terms_count;
}

154
src/printer_equation.c Normal file
View File

@@ -0,0 +1,154 @@
/* printer.c */
#include "computorv1.h"
/**
- [x] : ./computorv1 -b "3x² + 0x -0 = x"
Reduced form: 3x² - = 0
- [x] : ./computorv1 -b "3x² + 0x -7 = x"
Reduced form: 3x² - - 7 = 0
- [x] : ./computorv1 -b "-3x² + 2x -7 = x"
Reduced form: -+ x - 7 = 0
*/
static void print_reduced_form_beautify(s_polynom *polynom)
{
int i;
bool is_first_term;
double coefficient;
int exponent;
char *default_form;
default_form = "0 ";
ft_putstr("Reduced form: ");
i = 0;
is_first_term = true;
while (polynom[i].sign != TERM_SIGN_END)
{
coefficient = ft_fabs(polynom[i].coefficient);
exponent = polynom[i].exponent;
// if term is zero dont output
if (is_nearly_equal_zero(coefficient))
{
i++;
continue;
}
// default_form is not nedded anymore since something will be printed
default_form = "";
// print sign
// don't output '+' if is first term
if (!(polynom[i].sign == TERM_PLUS && is_first_term))
{
ft_putchar(polynom[i].sign);
}
// print term
if (!is_first_term)
{
ft_putchar(' ');
}
// for x⁰
if (exponent == 0)
{
printf("%g ", coefficient);
}
// for x¹
if (exponent == 1)
{
if (coefficient == 1)
printf("X ");
if (coefficient > 1)
printf("%gX ", coefficient);
}
// for x²
if (exponent >= 2)
{
if (coefficient == 1)
printf("X%s ", ft_superscript(exponent + '0'));
if (coefficient > 1)
printf("%gX%s ", coefficient, ft_superscript(exponent + '0'));
}
fflush(stdout);
i++;
is_first_term = false;
}
ft_printf("%s= 0\n", default_form);
}
void print_reduced_form(s_polynom *polynom, int degree)
{
int i;
bool is_first_term;
const s_polynom *found_term;
char sign;
if (flag_beautify_mode)
return print_reduced_form_beautify(polynom);
// reduced form
ft_putstr("Reduced form: ");
is_first_term = true;
i = 0;
while (i <= degree)
{
found_term = get_term_of_power(polynom, i);
// print sign
// don't output '+' if is first term
sign = found_term->sign == TERM_SIGN_END ? TERM_PLUS : found_term->sign;
if (is_first_term)
{
if (sign == TERM_MINUS)
ft_putchar(sign);
}
else
{
ft_putchar(sign);
}
// print term
if (!is_first_term)
ft_putchar(' ');
printf("%g * X^%i ", ft_fabs(found_term->coefficient), i);
fflush(stdout);
is_first_term = false;
i++;
}
ft_putstr("= 0\n");
}
void print_degree(s_polynom *polynom, int degree)
{
if (degree == 0)
{
if (polynom[0].coefficient == 0)
{
stop_errors("Any real number is a solution.\n");
}
else if (polynom[0].coefficient != 0)
{
stop_errors("No solution.\n");
}
}
else if (degree == 1)
{
ft_printf("Polynomial degree: %i\n", degree);
}
else if (degree == 2)
{
ft_printf("Polynomial degree: %i\n", degree);
}
else
{
ft_printf("Polynomial degree: %i\n", degree);
stop_errors("The polynomial degree is strictly greater than 2, I can't solve.\n");
}
}

272
src/printer_solutions.c Normal file
View File

@@ -0,0 +1,272 @@
/* printer.c */
#include "computorv1.h"
/**
* DEGREE 1
*/
static void print_solution_degree_1(s_solution_degree_1 solution)
{
ft_printf("The solution is:\n");
printf("%g\n", solution.solution);
}
/**
* DEGREE 2 PURE
*/
static void print_solution_pure_radicand_zero()
{
ft_printf("Discriminant is equal to zero, the solution is:\n");
printf("0\n");
}
static void print_solution_pure_radicand_positiv(s_solution_degree_2_pure solution)
{
double numerator;
double denominator;
ft_printf("Discriminant is strictly positive, the two solutions are:\n");
if (solution.numerator_sqrt_is_int && solution.denominator_sqrt_is_int)
{
numerator = solution.numerator_sqrt;
denominator = solution.denominator_sqrt;
reduce_fraction(&numerator, &denominator);
if (is_nearly_equal(denominator, 1))
{
printf("%g\n", numerator);
printf("-%g\n", numerator);
}
else
{
printf("%g/%g\n", numerator, denominator);
printf("-%g/%g\n", numerator, denominator);
}
}
else if (solution.numerator_sqrt_is_int)
{
printf("%g/√(%g)\n", solution.numerator_sqrt, solution.denominator);
printf("-%g/√(%g)\n", solution.numerator_sqrt, solution.denominator);
}
else if (solution.denominator_sqrt_is_int)
{
printf("√(%g)/%g\n", solution.numerator, solution.denominator_sqrt);
printf("-√(%g)/%g\n", solution.numerator, solution.denominator_sqrt);
}
else
{
numerator = solution.numerator;
denominator = solution.denominator;
reduce_fraction(&numerator, &denominator);
if (is_nearly_equal(denominator, 1))
{
printf("√(%g)\n", numerator);
printf("-√(%g)\n", numerator);
}
else
{
printf("√(%g/%g)\n", numerator, denominator);
printf("-√(%g/%g)\n", numerator, denominator);
}
}
}
static void print_solution_pure_radicand_negativ(s_solution_degree_2_pure solution)
{
double numerator;
double denominator;
ft_printf("Discriminant is strictly negative, the two complex solutions are:\n");
if (solution.numerator_sqrt_is_int && solution.denominator_sqrt_is_int)
{
numerator = solution.numerator_sqrt;
denominator = solution.denominator_sqrt;
reduce_fraction(&numerator, &denominator);
if (is_nearly_equal(denominator, 1))
{
printf("i%g\n", numerator);
printf("-i%g\n", numerator);
}
else
{
printf("i%g/%g\n", numerator, denominator);
printf("-i%g/%g\n", numerator, denominator);
}
}
else if (solution.numerator_sqrt_is_int)
{
printf("i%g/√(%g)\n", solution.numerator_sqrt, solution.denominator);
printf("-i%g/√(%g)\n", solution.numerator_sqrt, solution.denominator);
}
else if (solution.denominator_sqrt_is_int)
{
printf("i√(%g)/%g\n", solution.numerator, solution.denominator_sqrt);
printf("-i√(%g)/%g\n", solution.numerator, solution.denominator_sqrt);
}
else
{
numerator = solution.numerator;
denominator = solution.denominator;
reduce_fraction(&numerator, &denominator);
if (is_nearly_equal(denominator, 1))
{
printf("i√(%g)\n", numerator);
printf("-i√(%g)\n", numerator);
}
else
{
printf("i√(%g/%g)\n", numerator, denominator);
printf("-i√(%g/%g)\n", numerator, denominator);
}
}
}
/**
* DEGREE 2
*/
static void print_solution_delta_zero(s_solution_degree_2 solution)
{
ft_printf("Discriminant is equal to zero, the solution is:\n");
printf("%g\n", positiv_zero(solution.left_term));
}
static void print_solution_delta_positiv(s_solution_degree_2 solution)
{
ft_printf("Discriminant is strictly positive, the two solutions are:\n");
printf("%g\n", positiv_zero(solution.left_term - solution.right_term));
printf("%g\n", positiv_zero(solution.left_term + solution.right_term));
}
static void print_solution_delta_negativ(s_solution_degree_2 solution)
{
double denominator;
int denominator_sign;
double right_term_abs;
int right_term_sign;
bool has_first_term;
ft_printf("Discriminant is strictly negative, the two complex solutions are:\n");
has_first_term = false;
if (solution.all_int)
{
double first_term_numerator;
double first_term_denominator_abs;
double second_term_numerator;
double second_term_denominator_abs;
denominator = positiv_zero(solution.a * 2);
denominator_sign = ft_fsign(denominator);
first_term_denominator_abs = ft_fabs(denominator);
first_term_numerator = solution.b;
reduce_fraction(&first_term_numerator, &first_term_denominator_abs);
second_term_denominator_abs = ft_fabs(denominator);
second_term_numerator = positiv_zero(solution.delta_sqrt);
reduce_fraction(&second_term_numerator, &second_term_denominator_abs);
// solution 1
if (!is_nearly_equal_zero(first_term_numerator))
{
has_first_term = true;
printf("%g/%g ", first_term_numerator * -1 * denominator_sign, first_term_denominator_abs);
}
if (denominator_sign == -1)
printf("- ");
else if (has_first_term)
printf("+ "); // dont print '+' if it's first term
printf("%gi/%g\n", second_term_numerator, second_term_denominator_abs);
// solution 2
if (!is_nearly_equal_zero(first_term_numerator))
{
has_first_term = true;
printf("%g/%g ", first_term_numerator * -1 * denominator_sign, first_term_denominator_abs);
}
if (denominator_sign == 1)
printf("- ");
else if (has_first_term)
printf("+ "); // dont print '+' if it's first term
printf("%gi/%g\n", second_term_numerator, second_term_denominator_abs);
}
else
{
right_term_abs = positiv_zero(ft_fabs(solution.right_term));
right_term_sign = ft_fsign(solution.right_term);
// solution 1
if (!is_nearly_equal_zero(solution.left_term))
{
has_first_term = true;
printf("%g ", solution.left_term);
}
if (right_term_sign == 1)
printf("- ");
else if (has_first_term)
printf("+ "); // dont print '+' if it's first term
if (!is_nearly_equal_zero(right_term_abs))
printf("%g*i\n", right_term_abs);
// solution 2
if (!is_nearly_equal_zero(solution.left_term))
{
has_first_term = true;
printf("%g ", solution.left_term);
}
if (right_term_sign == -1)
printf("- ");
else if (has_first_term)
printf("+ "); // dont print '+' if it's first term
if (!is_nearly_equal_zero(right_term_abs))
printf("%g*i\n", right_term_abs);
}
}
void print_solution(s_solution *solution)
{
s_solution_degree_2 solution_d2;
s_solution_degree_2_pure solution_d2_pure;
e_delta_sign delta_sign;
e_radicand_sign radicand_sign;
// degree 1
if (solution->degree == 1)
{
return print_solution_degree_1(solution->solution_degree_1);
}
else if (solution->degree == 2 && solution->is_quadratic_pure)
{
solution_d2_pure = solution->solution_degree_2_pure;
radicand_sign = solution_d2_pure.radicand_sign;
if (radicand_sign == RADICAND_ZERO)
print_solution_pure_radicand_zero();
else if (radicand_sign == RADICAND_PLUS)
print_solution_pure_radicand_positiv(solution_d2_pure);
else if (radicand_sign == RADICAND_MINUS)
print_solution_pure_radicand_negativ(solution_d2_pure);
else
stop_errors("radicand sign is wrong : '%i' , radicand : '%g'", solution_d2_pure.radicand_sign, solution_d2_pure.radicand);
}
else if (solution->degree == 2 && !solution->is_quadratic_pure)
{
solution_d2 = solution->solution_degree_2;
delta_sign = solution_d2.delta_sign;
if (delta_sign == DELTA_ZERO)
print_solution_delta_zero(solution_d2);
else if (delta_sign == DELTA_PLUS)
print_solution_delta_positiv(solution_d2);
else if (delta_sign == DELTA_MINUS)
print_solution_delta_negativ(solution_d2);
else
stop_errors("delta sign is wrong : '%i' , delta : '%g'", solution_d2.delta_sign, solution_d2.delta);
}
else
{
stop_errors("The degree is '%i', it should already have been handled.", solution->degree);
}
}

View File

@@ -1,27 +0,0 @@
/* reduce.c */
#include "computorv1.h"
void reduce(s_term *terms, double *polynom)
{
int i;
int exponent;
double tmp;
i = 0;
while (terms[i].position != TERM_END)
{
// get coefficient with left sign
tmp = terms[i].coefficient;
if (terms[i].position == TERM_RIGHT)
{
tmp *= -1;
}
// add coefficient to exponent
exponent = terms[i].exponent;
polynom[exponent] += tmp;
i++;
}
}

74
src/reducer.c Normal file
View File

@@ -0,0 +1,74 @@
/* reduce.c */
#include "computorv1.h"
static double get_all_terms_with_exponent(s_term *terms, int exponent)
{
int i;
double coefficient;
int sign;
i = 0;
coefficient = 0.0;
while (terms[i].sign != TERM_SIGN_END)
{
if (terms[i].exponent != exponent)
{
i++;
continue;
}
// sign
sign = 1;
if (terms[i].position == TERM_RIGHT)
sign = -1;
// sign = terms[i].sign == TERM_PLUS ? -1 : 1;
// add coefficients
coefficient += terms[i].coefficient * sign;
i++;
}
return coefficient;
}
int reduce(s_term *terms, s_polynom *polynom, int max_exponent)
{
int i;
double tmp_coefficient;
int degree;
i = 0;
degree = 0;
while (max_exponent >= 0)
{
// if any terms contains this exponent, returns the addition of their coefficient
tmp_coefficient = get_all_terms_with_exponent(terms, max_exponent);
// skip if coefficient is null or no exponent
if (is_nearly_equal_zero(tmp_coefficient))
{
max_exponent--;
continue;
}
// get degree
if (max_exponent > degree)
degree = max_exponent;
// fill polynom
polynom[i].coefficient = tmp_coefficient;
polynom[i].exponent = max_exponent;
polynom[i].sign = ft_fsign(tmp_coefficient) == 1 ? TERM_PLUS : TERM_MINUS;
max_exponent--;
i++;
}
// fill END polynom
polynom[i].coefficient = 0.0;
polynom[i].exponent = 0;
polynom[i].sign = TERM_SIGN_END;
return degree;
}

111
src/solver.c Normal file
View File

@@ -0,0 +1,111 @@
/* solver.c */
#include "computorv1.h"
static void solve_degree_1(s_solution_degree_1 *solution, double a, double b)
{
solution->a = a;
solution->b = b;
solution->solution = positiv_zero(-b / a);
}
static void solve_degree_2(s_solution_degree_2 *solution, double a, double b, double c)
{
double delta;
double delta_sqrt;
int gcd;
solution->a = a;
solution->b = b;
solution->c = c;
delta = b * b - 4 * a * c;
solution->delta = delta; // Δ == b² - 4ac
solution->delta_sign = ft_fsign(delta); // DELTA_PLUS or DELTA_MINUS or DELTA_ZERO
solution->delta_absolute = ft_fabs(delta); // |Δ|
delta_sqrt = ft_sqrt(solution->delta_absolute, DOUBLE_PRECISION); // √|Δ|
solution->delta_sqrt = delta_sqrt;
/**
* SOLVE LEFT AND RIGHT TERMS AS DOUBLES
*/
if (!is_nearly_equal_zero(b))
solution->left_term = positiv_zero(-b / (2 * a)); // -b / 2a
if (!is_nearly_equal_zero(delta))
solution->right_term = positiv_zero(delta_sqrt / (2 * a)); // √|Δ| / 2a
/**
* COMPLEX : SOLVE TERMS AS FRACTIONS
*/
// check
if (solution->delta_sign != DELTA_MINUS)
return;
if (any_has_decimal_part((double[]){b, a, solution->delta_sqrt}, 3))
return;
solution->all_int = true;
// right term
gcd = gcd_int((int)solution->delta_sqrt, (int)(a * 2));
solution->right_term_numerator = solution->delta_sqrt / gcd;
solution->right_term_denominator = (a * 2) / gcd;
// left term
if (is_nearly_equal_zero(b))
return;
gcd = gcd_int((int)b, (int)(a * 2));
solution->left_term_numerator = -b / gcd;
solution->left_term_denominator = (a * 2) / gcd;
}
static void solve_degree_2_pure(s_solution_degree_2_pure *solution, double a, double c)
{
double radicand;
solution->a = a;
solution->c = c;
radicand = -c / a;
solution->radicand_sign = ft_fsign(radicand); // RADICAND_PLUS or RADICAND_MINUS or RADICAND_ZERO
solution->radicand_absolute = ft_fabs(radicand); // |radicand|
solution->radicand_sqrt = ft_sqrt(solution->radicand_absolute, DOUBLE_PRECISION); // √|radicand|
/**
* SQARE ROOTS
*/
solution->numerator = ft_fabs(c);
solution->numerator_sqrt = ft_sqrt(ft_fabs(c), DOUBLE_PRECISION);
solution->numerator_sqrt_is_int = !has_decimal_part(solution->numerator_sqrt);
solution->denominator = ft_fabs(a);
solution->denominator_sqrt = ft_sqrt(ft_fabs(a), DOUBLE_PRECISION);
solution->denominator_sqrt_is_int = !has_decimal_part(solution->denominator_sqrt);
}
void solve(const s_polynom *polynom, s_solution *solution)
{
double power2;
double power1;
double power0;
power2 = get_term_of_power(polynom, 2)->coefficient;
power1 = get_term_of_power(polynom, 1)->coefficient;
power0 = get_term_of_power(polynom, 0)->coefficient;
if (solution->degree == 1)
{
solve_degree_1(&solution->solution_degree_1, power1, power0);
}
else if (solution->degree == 2)
{
if (is_nearly_equal_zero(power1))
{
solution->is_quadratic_pure = true;
solve_degree_2_pure(&solution->solution_degree_2_pure, power2, power0);
}
else
solve_degree_2(&solution->solution_degree_2, power2, power1, power0);
}
}

View File

@@ -15,35 +15,17 @@ static void print_context_tokens()
i = 0;
while (tokens_g_err[i].type != TOKEN_END)
{
ft_dprintf(STDERR_FILENO, "token[%2i] - type : ", i);
if (tokens_g_err[i].type == TOKEN_VARIABLE)
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_VARIABLE");
else if (tokens_g_err[i].type == TOKEN_NUMBER_INT)
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_NUMBER_INT");
else if (tokens_g_err[i].type == TOKEN_NUMBER_DOUBLE)
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_NUMBER_DOUBLE");
else if (tokens_g_err[i].type == TOKEN_POWER)
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_POWER");
else if (tokens_g_err[i].type == TOKEN_SIGN_PLUS)
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_SIGN_PLUS");
else if (tokens_g_err[i].type == TOKEN_SIGN_MINUS)
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_SIGN_MINUS");
else if (tokens_g_err[i].type == TOKEN_FACTOR_MULT)
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_FACTOR_MULT");
else if (tokens_g_err[i].type == TOKEN_FACTOR_DIV)
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_FACTOR_DIV");
else if (tokens_g_err[i].type == TOKEN_EQUAL)
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_EQUAL");
else if (tokens_g_err[i].type == TOKEN_END)
ft_dprintf(STDERR_FILENO, "%20s", "TOKEN_END");
ft_dprintf(STDERR_FILENO, "token[%2i] - type : %22s", i, token_type_to_str(tokens_g_err[i].type));
ft_putstr(" - value : ");
if (tokens_g_err[i].type == TOKEN_NUMBER_INT)
{
ft_dprintf(STDERR_FILENO, "%i\n", tokens_g_err[i].value_int);
}
else if (tokens_g_err[i].type == TOKEN_NUMBER_INT_SUPER)
{
ft_dprintf(STDERR_FILENO, "%i\n", tokens_g_err[i].value_int);
}
else if (tokens_g_err[i].type == TOKEN_NUMBER_DOUBLE)
{
dprintf(STDERR_FILENO, "%g\n", tokens_g_err[i].value_double);
@@ -62,32 +44,12 @@ static void print_context_terms()
int i;
i = 0;
while (terms_g_err[i].position != TERM_END)
while (terms_g_err[i].position != TERM_POS_END)
{
ft_dprintf(STDERR_FILENO, "term[%2i] - ", i);
// position
ft_dprintf(STDERR_FILENO, "%8s : ", "position");
if (terms_g_err[i].position == TERM_LEFT)
ft_dprintf(STDERR_FILENO, "%10s", "TERM_LEFT");
else if (terms_g_err[i].position == TERM_RIGHT)
ft_dprintf(STDERR_FILENO, "%10s", "TERM_RIGHT");
else
ft_dprintf(STDERR_FILENO, "%10s", "");
// sign
ft_dprintf(STDERR_FILENO, " | %4s : ", "sign");
if (terms_g_err[i].sign == TERM_PLUS)
ft_dprintf(STDERR_FILENO, "%10s", "TERM_PLUS");
else if (terms_g_err[i].sign == TERM_MINUS)
ft_dprintf(STDERR_FILENO, "%10s", "TERM_MINUS");
else
ft_dprintf(STDERR_FILENO, "%10s", "");
// coefficient
ft_dprintf(STDERR_FILENO, "%8s : %10s", "position", term_position_to_str(terms_g_err[i].position));
ft_dprintf(STDERR_FILENO, " | %4s : %10s", "sign", term_sign_to_str(terms_g_err[i].sign));
dprintf(STDERR_FILENO, " | %10s : %13g", "coefficient", terms_g_err[i].coefficient);
// exponent
ft_dprintf(STDERR_FILENO, " | %8s : %d\n", "exponent", terms_g_err[i].exponent);
i++;
}
@@ -99,16 +61,86 @@ static void print_context_polynom()
int i;
i = 0;
while (i < polynom_len_g_err)
while (polynom_g_err[i].sign != TERM_SIGN_END)
{
dprintf(STDERR_FILENO, "polynom[%i]: %10g\n", i, polynom_g_err[i]);
dprintf(STDERR_FILENO, "polynom[%i] - sign: %15s(%c) - coefficient: %10g - exponent: %10i\n", i, term_sign_to_str(polynom_g_err[i].sign), polynom_g_err[i].sign, polynom_g_err[i].coefficient, polynom_g_err[i].exponent);
i++;
}
ft_putchar_fd('\n', STDERR_FILENO);
}
static void print_context_solution()
{
s_solution_degree_1 solution_d1;
s_solution_degree_2 solution_d2;
s_solution_degree_2_pure solution_d2_pure;
if (solution_g_err->degree == 1)
{
solution_d1 = solution_g_err->solution_degree_1;
dprintf(STDERR_FILENO, "degree 1 : x^1 ( ax + b )\n");
dprintf(STDERR_FILENO, "a : %10g ( a )\n", solution_d1.a);
dprintf(STDERR_FILENO, "b : %10g ( b )\n", solution_d1.b);
dprintf(STDERR_FILENO, "solution : %10g ( -b / a )\n", solution_d1.solution);
}
else if (solution_g_err->degree == 2)
{
if (solution_g_err->is_quadratic_pure)
{
solution_d2_pure = solution_g_err->solution_degree_2_pure;
dprintf(STDERR_FILENO, "degree 2 pure : radicand > 0 ( +-( -c / 2a ) )\n");
dprintf(STDERR_FILENO, " radicand == 0 ( 0 )\n");
dprintf(STDERR_FILENO, " radicand < 0 ( +-i( -c / 2a ) )\n");
dprintf(STDERR_FILENO, "a : %15g ( a )\n", solution_d2_pure.a);
dprintf(STDERR_FILENO, "c : %15g ( c )\n", solution_d2_pure.c);
dprintf(STDERR_FILENO, "radicand : %15g ( r == x² == -c / a )\n", solution_d2_pure.radicand);
dprintf(STDERR_FILENO, "radicand_sign : %15s ( '-' || '+' || '0' )\n", radicand_sign_to_str(solution_d2_pure.radicand_sign));
dprintf(STDERR_FILENO, "radicand_absolute : %15g ( |r| )\n", solution_d2_pure.radicand_absolute);
dprintf(STDERR_FILENO, "radicand_sqrt : %15g ( √|r| )\n", solution_d2_pure.radicand_sqrt);
dprintf(STDERR_FILENO, "numerator : %15g ( |c| )\n", solution_d2_pure.numerator);
dprintf(STDERR_FILENO, "numerator_sqrt : %15g ( √c )\n", solution_d2_pure.numerator_sqrt);
dprintf(STDERR_FILENO, "numerator_sqrt_is_int : %15i ( false if √c is double )\n", solution_d2_pure.numerator_sqrt_is_int);
dprintf(STDERR_FILENO, "denominator : %15g ( |a| )\n", solution_d2_pure.denominator);
dprintf(STDERR_FILENO, "denominator_sqrt : %15g ( √a )\n", solution_d2_pure.denominator_sqrt);
dprintf(STDERR_FILENO, "denominator_sqrt_is_int: %15i ( false if √a is double )\n", solution_d2_pure.denominator_sqrt_is_int);
}
else
{
solution_d2 = solution_g_err->solution_degree_2;
dprintf(STDERR_FILENO, "degree 2 : delta > 0 ( -b / 2a +- √Δ / 2a )\n");
dprintf(STDERR_FILENO, " delta == 0 ( -b / 2a )\n");
dprintf(STDERR_FILENO, " delta < 0 ( -b / 2a +- i√|Δ| / 2a )\n");
dprintf(STDERR_FILENO, "a : %15g ( a )\n", solution_d2.a);
dprintf(STDERR_FILENO, "b : %15g ( b )\n", solution_d2.b);
dprintf(STDERR_FILENO, "c : %15g ( c )\n", solution_d2.c);
dprintf(STDERR_FILENO, "delta : %15g ( Δ == b² - 4ac )\n", solution_d2.delta);
dprintf(STDERR_FILENO, "delta_sign : %15s ( '-' || '+' || '0' )\n", delta_sign_to_str(solution_d2.delta_sign));
dprintf(STDERR_FILENO, "delta_absolute : %15g ( |Δ| )\n", solution_d2.delta_absolute);
dprintf(STDERR_FILENO, "delta_sqrt : %15g ( √|Δ| )\n", solution_d2.delta_sqrt);
dprintf(STDERR_FILENO, "left_term : %15g ( -b / 2a )\n", solution_d2.left_term);
dprintf(STDERR_FILENO, "right_term : %15g ( √|Δ| / 2a )\n", solution_d2.right_term);
dprintf(STDERR_FILENO, "all_int : %15i ( are int : b, a, √|Δ| )\n", solution_d2.all_int);
dprintf(STDERR_FILENO, "left_term_numerator : %15i ( -b / left_gcd )\n", solution_d2.left_term_numerator);
dprintf(STDERR_FILENO, "left_term_denominator : %15i ( 2a / left_gcd )\n", solution_d2.left_term_denominator);
dprintf(STDERR_FILENO, "right_term_numerator : %15i ( √|Δ| / right_gcd )\n", solution_d2.right_term_numerator);
dprintf(STDERR_FILENO, "right_term_denominator : %15i ( 2a / right_gcd )\n", solution_d2.right_term_denominator);
}
}
ft_putchar_fd('\n', STDERR_FILENO);
}
void print_state()
{
if (!debug_mode)
if (!flag_debug_mode)
return;
ft_dprintf(STDERR_FILENO, "\nSTATE :\n");
if (input_g_err)
@@ -119,45 +151,37 @@ void print_state()
print_context_terms();
if (polynom_g_err)
print_context_polynom();
if (solution_g_err)
print_context_solution();
}
int stop_errors(e_program_error err, const char *details, ...)
void stop_errors(const char *description, ...)
{
// the base error message
const char *msg = "error: error type is out of range";
// map error codes to messages
const char *error_messages[ERROR_SENTINEL] = {
[ERROR_BASE] = "undefined error",
[ARGUMENTS_ERROR] = "arguments error",
[ERROR_UNKNOWN_TOKEN] = "LEXER - unknown token",
[ERROR_NUMBER_TOO_BIG] = "LEXER - number is too big",
[ERROR_PARSING] = "PARSER - too much terms to parse",
[ERROR_TOKEN_POSITION] = "PARSER - token position is not good in grammar",
[ERROR_VAR_DIFF] = "PARSER - expression must only contain one variable",
[ERROR_TOKEN_COUNT] = "LEXER - token count error",
[ERROR_TERM_COUNT] = "PARSER - term count error",
};
// override msg if err is in the error_messages array
if (err >= ERROR_BASE && err < ERROR_SENTINEL)
// print context
if (flag_debug_mode)
{
msg = error_messages[err];
print_state();
}
// print context
print_state();
// print red ERROR
if (flag_debug_mode)
{
ft_putstr_fd("\e[1;31mERROR:\e[0m ", STDERR_FILENO);
}
// print the base message
ft_dprintf(STDERR_FILENO, "error: (%i) %s - details: ", err, msg);
// print the formatted details
// print the formatted description
va_list args;
va_start(args, details);
ft_vdprintf(STDERR_FILENO, details, args);
va_start(args, description);
ft_vdprintf(STDERR_FILENO, description, args);
va_end(args);
ft_putchar_fd('\n', STDERR_FILENO);
exit(err);
// print the base message
if (flag_debug_mode)
{
ft_dprintf(STDERR_FILENO, " (errno[%d] : %s)\n", errno, strerror(errno));
}
// stop program
exit(EXIT_FAILURE);
}

84
src/utils/math.c Normal file
View File

@@ -0,0 +1,84 @@
/* printer.c */
#include "computorv1.h"
bool is_nearly_equal(double num, int compare)
{
return is_nearly_equal_zero(num - compare);
}
bool is_nearly_equal_zero(double num)
{
if (num > DOUBLE_PRECISION)
return false;
if (num < -DOUBLE_PRECISION)
return false;
return true;
}
const s_polynom *get_term_of_power(const s_polynom *polynom, int power)
{
int i;
i = 0;
while (polynom[i].sign != TERM_SIGN_END)
{
if (polynom[i].exponent == power)
break;
i++;
}
return &polynom[i];
}
double positiv_zero(double num)
{
if (is_nearly_equal_zero(num))
return 0.0;
return num;
}
bool has_decimal_part(double num)
{
return (!is_nearly_equal(num, (int)num));
}
bool any_has_decimal_part(double *num, size_t len)
{
while (len > 0)
{
if (has_decimal_part(num[len - 1]))
return true;
len--;
}
return false;
}
// find GCD of two integers using euclidean algorithm
int gcd_int(int a, int b)
{
int tmp;
while (b != 0)
{
tmp = b;
b = a % b;
a = tmp;
}
return ft_abs(a);
}
// returns the gcd, and modify arguments with new reduced values
int reduce_fraction(double *numerator, double *denominator)
{
int gcd;
if (any_has_decimal_part((double[]){*numerator, *denominator}, 2))
return 0;
gcd = gcd_int((int)*numerator, (int)*denominator);
*numerator /= gcd;
*denominator /= gcd;
return gcd;
}

16
src/utils/print_debug.c Normal file
View File

@@ -0,0 +1,16 @@
/* printer.c */
#include "computorv1.h"
void print_debug(const char *description, ...)
{
if (!flag_debug_mode)
return;
// print the formatted description
va_list args;
va_start(args, description);
// ft_vdprintf(STDERR_FILENO, description, args); // it's not handling floats for the moment
vdprintf(STDERR_FILENO, description, args);
va_end(args);
}

View File

@@ -4,56 +4,90 @@
const char *token_type_to_str(e_token_type enum_value)
{
if (enum_value > TOKEN_END || enum_value < TOKEN_VARIABLE)
if (enum_value == TOKEN_VARIABLE)
return "TOKEN_VARIABLE";
else if (enum_value == TOKEN_NUMBER_INT)
return "TOKEN_NUMBER_INT";
else if (enum_value == TOKEN_NUMBER_DOUBLE)
return "TOKEN_NUMBER_DOUBLE";
else if (enum_value == TOKEN_NUMBER_INT_SUPER)
return "TOKEN_NUMBER_INT_SUPER";
else if (enum_value == TOKEN_POWER)
return "TOKEN_POWER";
else if (enum_value == TOKEN_SIGN_PLUS)
return "TOKEN_SIGN_PLUS";
else if (enum_value == TOKEN_SIGN_MINUS)
return "TOKEN_SIGN_MINUS";
else if (enum_value == TOKEN_FACTOR_MULT)
return "TOKEN_FACTOR_MULT";
else if (enum_value == TOKEN_FACTOR_DIV)
return "TOKEN_FACTOR_DIV";
else if (enum_value == TOKEN_EQUAL)
return "TOKEN_EQUAL";
else if (enum_value == TOKEN_END)
return "TOKEN_END";
else
return "invalid enum value";
static const char *const token_type_str[TOKEN_END + 1] = {
[TOKEN_VARIABLE] = "TOKEN_VARIABLE",
[TOKEN_NUMBER_INT] = "TOKEN_NUMBER_INT",
[TOKEN_NUMBER_DOUBLE] = "TOKEN_NUMBER_DOUBLE",
[TOKEN_POWER] = "TOKEN_POWER",
[TOKEN_SIGN_PLUS] = "TOKEN_SIGN_PLUS",
[TOKEN_SIGN_MINUS] = "TOKEN_SIGN_MINUS",
[TOKEN_FACTOR_MULT] = "TOKEN_FACTOR_MULT",
[TOKEN_FACTOR_DIV] = "TOKEN_FACTOR_DIV",
[TOKEN_EQUAL] = "TOKEN_EQUAL",
[TOKEN_END] = "TOKEN_END"};
return token_type_str[enum_value];
}
const char *token_tag_to_str(e_token_tag enum_value)
{
if (enum_value > TOKEN_FACTOR || enum_value < TOKEN_NO_TAG)
if (enum_value == TOKEN_NO_TAG)
return "TOKEN_NO_TAG";
else if (enum_value == TOKEN_NUMBER)
return "TOKEN_NUMBER";
else if (enum_value == TOKEN_SIGN)
return "TOKEN_SIGN";
else if (enum_value == TOKEN_FACTOR)
return "TOKEN_FACTOR";
else
return "invalid enum value";
static const char *const token_tag_str[TOKEN_FACTOR + 1] = {
[TOKEN_NO_TAG] = "TOKEN_NO_TAG",
[TOKEN_NUMBER] = "TOKEN_NUMBER",
[TOKEN_SIGN] = "TOKEN_SIGN",
[TOKEN_FACTOR] = "TOKEN_FACTOR"};
return token_tag_str[enum_value];
}
const char *term_position_to_str(e_term_position enum_value)
{
if (enum_value > TERM_END || enum_value < TERM_LEFT)
if (enum_value == TERM_LEFT)
return "TERM_LEFT";
else if (enum_value == TERM_RIGHT)
return "TERM_RIGHT";
else if (enum_value == TERM_POS_END)
return "TERM_POS_END";
else
return "invalid enum value";
static const char *const term_position_str[TERM_END + 1] = {
[TERM_LEFT] = "TERM_LEFT",
[TERM_RIGHT] = "TERM_RIGHT",
[TERM_END] = "TERM_END"};
return term_position_str[enum_value];
}
const char *term_sign_to_str(e_term_sign enum_value)
{
if (enum_value > TERM_NULL || enum_value < TERM_PLUS)
if (enum_value == TERM_PLUS)
return "TERM_PLUS";
else if (enum_value == TERM_MINUS)
return "TERM_MINUS";
else if (enum_value == TERM_SIGN_END)
return "TERM_SIGN_END";
else
return "invalid enum value";
}
const char *delta_sign_to_str(e_delta_sign enum_value)
{
if (enum_value == DELTA_PLUS)
return "DELTA_PLUS";
else if (enum_value == DELTA_MINUS)
return "DELTA_MINUS";
else if (enum_value == DELTA_ZERO)
return "DELTA_ZERO";
else
return "invalid enum value";
}
const char *radicand_sign_to_str(e_radicand_sign enum_value)
{
if (enum_value == RADICAND_PLUS)
return "RADICAND_PLUS";
else if (enum_value == RADICAND_MINUS)
return "RADICAND_MINUS";
else if (enum_value == RADICAND_ZERO)
return "RADICAND_ZERO";
else
return "invalid enum value";
static const char *const term_sign_str[TERM_NULL + 1] = {
[TERM_PLUS] = "TERM_PLUS",
[TERM_MINUS] = "TERM_MINUS",
[TERM_NULL] = "TERM_NULL"};
return term_sign_str[enum_value];
}

540
tester.sh Normal file

File diff suppressed because one or more lines are too long