Compare commits
46 Commits
93647b56b5
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4969be8a0d | ||
|
|
1962b87895 | ||
|
|
3732c0b777 | ||
|
|
2393c1eea4 | ||
|
|
858d4f3ac8 | ||
|
|
487191c516 | ||
|
|
abc5754bba | ||
|
|
c99bdfc63a | ||
|
|
f1a6a8e586 | ||
|
|
2824414f53 | ||
|
|
0603050d30 | ||
|
|
f25291f12f | ||
|
|
b185647d2b | ||
|
|
7e16bb5b6f | ||
|
|
aa78af4e0f | ||
|
|
6c6accc289 | ||
|
|
840f5bcfdf | ||
|
|
31469af23f | ||
|
|
201f2fa0ce | ||
|
|
7b5aa97c0c | ||
|
|
3761adcf11 | ||
|
|
bbe0d65b1f | ||
|
|
d770d7fc87 | ||
|
|
00f380f5df | ||
|
|
7978f0d706 | ||
|
|
b0e6483a68 | ||
|
|
a91ad5461f | ||
|
|
37d9fa2f24 | ||
|
|
6d2e7922bc | ||
|
|
500b6fd932 | ||
|
|
cd6e2327e9 | ||
|
|
647c9a54b1 | ||
|
|
8445604656 | ||
|
|
5077db3bc6 | ||
|
|
ca99f43fe4 | ||
|
|
43b4def6ce | ||
|
|
0fcfd0260d | ||
|
|
23c788d0c2 | ||
|
|
f62a6fe94f | ||
|
|
09701f8884 | ||
|
|
f373fef4ac | ||
|
|
8c22b98d88 | ||
|
|
4c13d21e1f | ||
|
|
16c57c9bea | ||
|
|
4b6ad34720 | ||
|
|
0046409c89 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,4 @@
|
||||
computorv1
|
||||
computor
|
||||
|
||||
# ---> C
|
||||
# Prerequisites
|
||||
|
||||
55
.vscode/launch.json
vendored
Normal file
55
.vscode/launch.json
vendored
Normal 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
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"window.title": "${rootName} — ${activeEditorShort}"
|
||||
}
|
||||
23
.vscode/tasks.json
vendored
Normal file
23
.vscode/tasks.json
vendored
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
33
Makefile
33
Makefile
@@ -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 $(B_PURPLE)"\n---------------------------------------------\n1. run with flag '-d' as last \n"$(RESET)
|
||||
./$(NAME) "3.4 * x^2 + 1 * x^1 - 2.0 * x^0 = 5.123 * x^1" -d
|
||||
@echo $(B_PURPLE)"\n---------------------------------------------\n2. run without flag \n"$(RESET)
|
||||
./$(NAME) "3 * x^2 + 5 * x^1 - 2 * x^0 = 5 * x^1"
|
||||
@echo $(B_PURPLE)"\n---------------------------------------------\n3. run with flag '-d' as first \n"$(RESET)
|
||||
./$(NAME) -d "3*x^2 + 2*x = 0"
|
||||
@echo $(B_PURPLE)"\n---------------------------------------------\n4. run with wrong flag '-e' \n"$(RESET)
|
||||
-./$(NAME) -d -e "3*x^2 + 2*x -7x^4 = x^4"
|
||||
@echo $(B_PURPLE)"\n---------------------------------------------\n5. run \n"$(RESET)
|
||||
./$(NAME) -d "3*x^2 + 2*x -7x^3 = x^3"
|
||||
@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)
|
||||
|
||||
192
README.md
192
README.md
@@ -1,47 +1,171 @@
|
||||
# 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
|
||||
|
||||
- project intra : https://projects.intra.42.fr/projects/42cursus-computorv1
|
||||
- project luke : https://github.com/LuckyLaszlo/computorv1
|
||||
- project intra : https://projects.intra.42.fr/projects/42cursus-computorv1
|
||||
- project luke : https://github.com/LuckyLaszlo/computorv1
|
||||
|
||||
## install
|
||||
|
||||
this project uses submodules (maybe recursively), so either :
|
||||
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
|
||||
```
|
||||
|
||||
## Newton–Raphson 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`
|
||||
|
||||
754
docs/computorv1.correction.2026.html
Normal file
754
docs/computorv1.correction.2026.html
Normal 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: "futura-pt", "Helvetica", "Sans serif"; 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">Don’t 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>
|
||||
@@ -1,46 +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_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, // =
|
||||
TOKEN_END // null (end of input)
|
||||
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, // =
|
||||
} e_token_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TOKEN_NO_TAG,
|
||||
TOKEN_NO_TAG = 0,
|
||||
TOKEN_NUMBER,
|
||||
TOKEN_SIGN,
|
||||
TOKEN_FACTOR,
|
||||
@@ -58,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
|
||||
@@ -66,16 +81,16 @@ int lexerize(const char *input, s_token *tokens);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TERM_LEFT, // a in "a = b"
|
||||
TERM_RIGHT, // b in "a = b"
|
||||
TERM_END, // last term
|
||||
TERM_POS_END = 0, // for last term
|
||||
TERM_LEFT, // a in "a = b"
|
||||
TERM_RIGHT, // b in "a = b"
|
||||
} 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
|
||||
@@ -86,20 +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
|
||||
*/
|
||||
|
||||
void print_state();
|
||||
int stop_errors(const char *format, ...);
|
||||
void stop_errors(const char *format, ...);
|
||||
|
||||
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* UTILS/PRINT_ENUMS.C
|
||||
@@ -109,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
|
||||
@@ -117,9 +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 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
2
libft
Submodule libft updated: b64ede50af...9ac98cb1f5
292
src/computorv1.c
292
src/computorv1.c
@@ -1,292 +0,0 @@
|
||||
/* computorv1.c */
|
||||
|
||||
#include "computorv1.h"
|
||||
|
||||
/**
|
||||
* GLOBALS
|
||||
*/
|
||||
|
||||
bool flag_debug_mode;
|
||||
bool flag_loop_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("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("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)
|
||||
{
|
||||
int i;
|
||||
char *input;
|
||||
e_program_mode program_mode;
|
||||
|
||||
// init flags
|
||||
flag_debug_mode = false;
|
||||
flag_loop_mode = false;
|
||||
|
||||
// check arguments
|
||||
program_mode = MODE_ARGV;
|
||||
if (ac == 1)
|
||||
{
|
||||
program_mode = MODE_STDIN;
|
||||
}
|
||||
else if (ac > 1)
|
||||
{
|
||||
// get flags
|
||||
input = NULL;
|
||||
i = 1;
|
||||
while (i < ac)
|
||||
{
|
||||
if ((ft_strcmp(av[i], "-d") == 0))
|
||||
{
|
||||
flag_debug_mode = true;
|
||||
}
|
||||
else if ((ft_strcmp(av[i], "-l") == 0))
|
||||
{
|
||||
flag_loop_mode = true;
|
||||
}
|
||||
else if (ft_strlen(av[i]) == 2 && av[i][0] == '-')
|
||||
{
|
||||
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_argv(input);
|
||||
}
|
||||
else if (program_mode == MODE_STDIN)
|
||||
{
|
||||
launch_stdin();
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
150
src/launcher.c
Normal file
150
src/launcher.c
Normal 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();
|
||||
}
|
||||
498
src/lexer.c
498
src/lexer.c
@@ -2,270 +2,352 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
if (ft_isalpha(input[input_pos]))
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (ft_isalpha(input[input_pos]))
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// token is int "123"
|
||||
static bool token_is_number_int(const char *input, int input_pos, int *token_size)
|
||||
{
|
||||
int number_size;
|
||||
int max_number_size;
|
||||
int 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)
|
||||
{
|
||||
if (ft_isdigit(input[input_pos + number_size]))
|
||||
{
|
||||
number_size++;
|
||||
}
|
||||
else if (input[input_pos + number_size] == '.')
|
||||
{
|
||||
if (ft_isdigit(input[input_pos + number_size + 1]))
|
||||
{
|
||||
// number is double
|
||||
return false;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (number_size > max_number_size)
|
||||
{
|
||||
stop_errors(&input[input_pos]);
|
||||
}
|
||||
*token_size = number_size;
|
||||
return true;
|
||||
while (input[input_pos + number_size] != '\0')
|
||||
{
|
||||
if (ft_isdigit(input[input_pos + number_size]))
|
||||
{
|
||||
number_size++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (number_size == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (is_number_out_of_int_range(&input[input_pos], number_size))
|
||||
{
|
||||
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;
|
||||
int number_size;
|
||||
bool has_dot;
|
||||
|
||||
if (!ft_isdigit(input[input_pos]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
has_dot = false;
|
||||
number_size = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
if (ft_isdigit(input[input_pos + number_size]))
|
||||
{
|
||||
number_size++;
|
||||
}
|
||||
else if (input[input_pos + number_size] == '.')
|
||||
{
|
||||
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)
|
||||
{
|
||||
stop_errors(&input[input_pos]);
|
||||
}
|
||||
*token_size = number_size;
|
||||
return true;
|
||||
while (input[input_pos + number_size] != '\0')
|
||||
{
|
||||
if (ft_isdigit(input[input_pos + number_size]))
|
||||
{
|
||||
number_size++;
|
||||
}
|
||||
else if (input[input_pos + number_size] == '.' && !has_dot)
|
||||
{
|
||||
has_dot = true;
|
||||
number_size++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (is_number_out_of_int_range(&input[input_pos], number_size))
|
||||
{
|
||||
*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;
|
||||
}
|
||||
|
||||
// token is '^' or "**"
|
||||
static bool token_is_power(const char *input, int input_pos, int *token_size)
|
||||
{
|
||||
if (input[input_pos] == '^')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
if (ft_memcmp(&input[input_pos], "**", 2) == 0)
|
||||
{
|
||||
*token_size = 2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (input[input_pos] == '^')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
if (ft_memcmp(&input[input_pos], "**", 2) == 0)
|
||||
{
|
||||
*token_size = 2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// token is '+'
|
||||
static bool token_is_sign_plus(const char *input, int input_pos, int *token_size)
|
||||
{
|
||||
if (input[input_pos] == '+')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (input[input_pos] == '+')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// token is '-'
|
||||
static bool token_is_sign_minus(const char *input, int input_pos, int *token_size)
|
||||
{
|
||||
if (input[input_pos] == '-')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (input[input_pos] == '-')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// token is '*'
|
||||
static bool token_is_factor_multiplication(const char *input, int input_pos, int *token_size)
|
||||
{
|
||||
if (input[input_pos] == '*')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (input[input_pos] == '*')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// token is '/' or ':'
|
||||
static bool token_is_factor_division(const char *input, int input_pos, int *token_size)
|
||||
{
|
||||
if (input[input_pos] == '/')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
if (input[input_pos] == ':')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (input[input_pos] == '/')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
if (input[input_pos] == ':')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// token is '='
|
||||
static bool token_is_equal(const char *input, int input_pos, int *token_size)
|
||||
{
|
||||
if (input[input_pos] == '=')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (input[input_pos] == '=')
|
||||
{
|
||||
*token_size = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
int tokens_count;
|
||||
int input_pos;
|
||||
int token_size;
|
||||
// bool has_equal;
|
||||
|
||||
tokens_count = 0;
|
||||
input_pos = 0;
|
||||
while (input[input_pos])
|
||||
{
|
||||
token_size = 0;
|
||||
// has_equal = false;
|
||||
tokens_count = 0;
|
||||
input_pos = 0;
|
||||
while (input[input_pos])
|
||||
{
|
||||
token_size = 0;
|
||||
|
||||
if (input[input_pos] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (input[input_pos] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (token_is_variable(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_VARIABLE;
|
||||
tokens[tokens_count].tag = TOKEN_NO_TAG;
|
||||
tokens[tokens_count].value_char = 'x';
|
||||
}
|
||||
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))
|
||||
{
|
||||
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_power(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_POWER;
|
||||
tokens[tokens_count].tag = TOKEN_NO_TAG;
|
||||
tokens[tokens_count].value_char = '^';
|
||||
}
|
||||
else if (token_is_sign_plus(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_SIGN_PLUS;
|
||||
tokens[tokens_count].tag = TOKEN_SIGN;
|
||||
tokens[tokens_count].value_char = input[input_pos];
|
||||
}
|
||||
else if (token_is_sign_minus(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_SIGN_MINUS;
|
||||
tokens[tokens_count].tag = TOKEN_SIGN;
|
||||
tokens[tokens_count].value_char = input[input_pos];
|
||||
}
|
||||
else if (token_is_factor_multiplication(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_FACTOR_MULT;
|
||||
tokens[tokens_count].tag = TOKEN_FACTOR;
|
||||
tokens[tokens_count].value_char = input[input_pos];
|
||||
}
|
||||
else if (token_is_factor_division(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_FACTOR_DIV;
|
||||
tokens[tokens_count].tag = TOKEN_FACTOR;
|
||||
tokens[tokens_count].value_char = input[input_pos];
|
||||
}
|
||||
else if (token_is_equal(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_EQUAL;
|
||||
tokens[tokens_count].tag = TOKEN_NO_TAG;
|
||||
tokens[tokens_count].value_char = '=';
|
||||
}
|
||||
else
|
||||
{
|
||||
stop_errors(&input[input_pos]);
|
||||
}
|
||||
if (token_is_variable(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_VARIABLE;
|
||||
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_int_super(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_NUMBER_INT_SUPER;
|
||||
tokens[tokens_count].tag = TOKEN_NUMBER;
|
||||
tokens[tokens_count].value_int = ft_atoi_superscript(&input[input_pos]);
|
||||
}
|
||||
else if (token_is_power(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_POWER;
|
||||
tokens[tokens_count].tag = TOKEN_NO_TAG;
|
||||
tokens[tokens_count].value_char = '^';
|
||||
}
|
||||
else if (token_is_sign_plus(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_SIGN_PLUS;
|
||||
tokens[tokens_count].tag = TOKEN_SIGN;
|
||||
tokens[tokens_count].value_char = input[input_pos];
|
||||
}
|
||||
else if (token_is_sign_minus(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_SIGN_MINUS;
|
||||
tokens[tokens_count].tag = TOKEN_SIGN;
|
||||
tokens[tokens_count].value_char = input[input_pos];
|
||||
}
|
||||
else if (token_is_factor_multiplication(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_FACTOR_MULT;
|
||||
tokens[tokens_count].tag = TOKEN_FACTOR;
|
||||
tokens[tokens_count].value_char = input[input_pos];
|
||||
}
|
||||
else if (token_is_factor_division(input, input_pos, &token_size))
|
||||
{
|
||||
tokens[tokens_count].type = TOKEN_FACTOR_DIV;
|
||||
tokens[tokens_count].tag = TOKEN_FACTOR;
|
||||
tokens[tokens_count].value_char = input[input_pos];
|
||||
}
|
||||
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("input[input_pos] is not any token: %s\n", &input[input_pos]);
|
||||
}
|
||||
|
||||
tokens_count++;
|
||||
if (token_size == 0)
|
||||
{
|
||||
stop_errors(&input[input_pos]);
|
||||
}
|
||||
input_pos += token_size;
|
||||
}
|
||||
tokens_count++;
|
||||
if (token_size == 0)
|
||||
{
|
||||
stop_errors("token_size is 0 : %s\n", &input[input_pos]);
|
||||
}
|
||||
input_pos += token_size;
|
||||
}
|
||||
|
||||
tokens[tokens_count].type = TOKEN_END;
|
||||
tokens[tokens_count].tag = TOKEN_NO_TAG;
|
||||
tokens[tokens_count].value_char = '\0';
|
||||
// if (!has_equal)
|
||||
// stop_errors("the input polynomial does not contains an equal sign, it's an expression not an equation.\n");
|
||||
|
||||
return tokens_count;
|
||||
tokens[tokens_count].type = TOKEN_END;
|
||||
tokens[tokens_count].tag = TOKEN_NO_TAG;
|
||||
tokens[tokens_count].value_char = '\0';
|
||||
}
|
||||
|
||||
181
src/main.c
Normal file
181
src/main.c
Normal 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);
|
||||
}
|
||||
186
src/parser.c
186
src/parser.c
@@ -16,28 +16,44 @@
|
||||
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;
|
||||
// we can have two signs in a row, like "3 - -2" or "3 - +2"
|
||||
j = 0;
|
||||
while (j < 2)
|
||||
{
|
||||
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 (i == 0) // if most left term, 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
|
||||
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;
|
||||
return TERM_PLUS;
|
||||
ret_sign = TERM_PLUS;
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
@@ -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
|
||||
// - '' -> exponent 0
|
||||
// - [*] [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++;
|
||||
// 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 (token_sequence(&tokens[i], (e_token_type[]){TOKEN_FACTOR_MULT, TOKEN_VARIABLE, TOKEN_POWER, TOKEN_NUMBER_INT}, 4))
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
else if (tokens[i].type == TOKEN_FACTOR_MULT)
|
||||
{
|
||||
// token is '*'
|
||||
i++;
|
||||
if (tokens[i].type == TOKEN_VARIABLE)
|
||||
{
|
||||
// tokens are '*x'
|
||||
i++;
|
||||
*token_count = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
stop_errors("at exponent place, after a '*' we should have a 'var', but instead got : '%s' (token number %i)", token_type_to_str(tokens[i].type), i);
|
||||
}
|
||||
ret_exponent = 1;
|
||||
}
|
||||
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("at exponent place, we should have an int, but instead got : '%s' (token number %i)", token_type_to_str(tokens[i].type), i);
|
||||
}
|
||||
|
||||
return tokens[i].value_int;
|
||||
return ret_exponent;
|
||||
}
|
||||
|
||||
static void check_variables(s_token *tokens)
|
||||
@@ -191,7 +222,7 @@ static void check_variables(s_token *tokens)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
terms[terms_count].coefficient = 0;
|
||||
terms[terms_count].exponent = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
stop_errors("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;
|
||||
// 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;
|
||||
}
|
||||
154
src/printer_equation.c
Normal file
154
src/printer_equation.c
Normal 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
272
src/printer_solutions.c
Normal 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);
|
||||
}
|
||||
}
|
||||
27
src/reduce.c
27
src/reduce.c
@@ -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
74
src/reducer.c
Normal 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
111
src/solver.c
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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,11 +61,81 @@ 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()
|
||||
@@ -119,23 +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(const char *description, ...)
|
||||
void stop_errors(const char *description, ...)
|
||||
{
|
||||
// print context (if debug mode)
|
||||
print_state();
|
||||
// print context
|
||||
if (flag_debug_mode)
|
||||
{
|
||||
print_state();
|
||||
}
|
||||
|
||||
ft_putstr_fd("\e[1;31mERROR:\e[0m ", STDERR_FILENO);
|
||||
// print red ERROR
|
||||
if (flag_debug_mode)
|
||||
{
|
||||
ft_putstr_fd("\e[1;31mERROR:\e[0m ", STDERR_FILENO);
|
||||
}
|
||||
|
||||
// print the formatted description
|
||||
va_list args;
|
||||
va_start(args, description);
|
||||
ft_vdprintf(STDERR_FILENO, description, args);
|
||||
va_end(args);
|
||||
ft_putchar_fd('\n', STDERR_FILENO);
|
||||
|
||||
// print the base message
|
||||
ft_dprintf(STDERR_FILENO, " (errno[%d] : %s)\n", errno, strerror(errno));
|
||||
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
84
src/utils/math.c
Normal 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
16
src/utils/print_debug.c
Normal 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);
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
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];
|
||||
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";
|
||||
}
|
||||
Reference in New Issue
Block a user