From 4515fc0b8d0936c64c4fe08227c7aaf0c9300f5d Mon Sep 17 00:00:00 2001 From: Efe Kaan Turhan Date: Wed, 3 Dec 2025 13:25:27 +0100 Subject: [PATCH] Doblespiel V1 --- .idea/.gitignore | 8 ++ .idea/editor.xml | 344 +++++++++++++++++++++++++++++++++++++++++++++++ .idea/vcs.xml | 6 + bintree.c | 89 ++++++++++-- bintree.h | 15 ++- bintree.o | Bin 0 -> 5878 bytes doble.exe | Bin 0 -> 81586 bytes highscore.c | 2 + highscore.o | Bin 0 -> 8731 bytes highscores.txt | 4 +- main.c | 3 + main.o | Bin 0 -> 6051 bytes makefile | 44 +++--- numbers.c | 87 ++++++++++-- numbers.h | 6 +- numbers.o | Bin 0 -> 5500 bytes stack.c | 44 +++--- stack.h | 24 ++-- stack.o | Bin 0 -> 3839 bytes test_numbers.c | 62 +++++++++ test_stack.c | 68 ++++++++++ timer.o | Bin 0 -> 3066 bytes 22 files changed, 714 insertions(+), 92 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/editor.xml create mode 100644 .idea/vcs.xml create mode 100644 bintree.o create mode 100644 doble.exe create mode 100644 highscore.o create mode 100644 main.o create mode 100644 numbers.o create mode 100644 stack.o create mode 100644 test_numbers.c create mode 100644 test_stack.c create mode 100644 timer.o diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/editor.xml b/.idea/editor.xml new file mode 100644 index 0000000..25c6c37 --- /dev/null +++ b/.idea/editor.xml @@ -0,0 +1,344 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/bintree.c b/bintree.c index 5cf82a9..da31623 100644 --- a/bintree.c +++ b/bintree.c @@ -1,36 +1,97 @@ +#include +#include #include #include "stack.h" #include "bintree.h" -//TODO: binären Suchbaum implementieren -/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv), - * `clearTree`: gibt den gesamten Baum frei (rekursiv), - * `treeSize`: zählt die Knoten im Baum (rekursiv), - * `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */ +// Statischer Stack für die Iteration (ersetzt das externe Argument) +static StackNode *iteratorStack = NULL; -// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates -// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) { + if (root == NULL) { + TreeNode *newNode = (TreeNode *)malloc(sizeof(TreeNode)); + if (!newNode) return NULL; + newNode->data = malloc(dataSize); + if (newNode->data) { + memcpy(newNode->data, data, dataSize); + } else { + free(newNode); + return NULL; + } + + newNode->left = NULL; + newNode->right = NULL; + + if (isDuplicate) *isDuplicate = 0; // Neu eingefügt + return newNode; + } + + int cmp = compareFct(data, root->data); + + if (cmp < 0) { + root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate); + } else if (cmp > 0) { + root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate); + } else { + // Element existiert bereits + if (isDuplicate == NULL) { + // Wenn isDuplicate NULL ist, explizit erlauben (siehe Aufgabenstellung/Kommentar) + // Wir fügen es rechts ein + root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate); + } else { + // Duplikat melden und NICHT einfügen + *isDuplicate = 1; + } + } + return root; +} + +// Hilfsfunktion: Schiebt Node und alle linken Kinder auf den Stack +static void pushLeft(StackNode **stack, TreeNode *node) { + while (node != NULL) { + *stack = push(*stack, node); + node = node->left; + } } -// Iterates over the tree given by root. Follows the usage of strtok. If tree is NULL, the next entry of the last tree given is returned in ordering direction. -// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, -// push the top node and push all its left nodes. void *nextTreeData(TreeNode *root) { + // Wenn root übergeben wird, starte neue Iteration + if (root != NULL) { + clearStack(iteratorStack); + iteratorStack = NULL; + pushLeft(&iteratorStack, root); + } + if (top(iteratorStack) == NULL) { + return NULL; // Ende der Iteration + } + + TreeNode *current = (TreeNode *)top(iteratorStack); + iteratorStack = pop(iteratorStack); + void *data = current->data; + + // Wenn es einen rechten Teilbaum gibt, verarbeite diesen als nächstes + if (current->right != NULL) { + pushLeft(&iteratorStack, current->right); + } + + return data; } -// Releases all memory resources (including data copies). void clearTree(TreeNode *root) { - + if (root == NULL) return; + clearTree(root->left); + clearTree(root->right); + if (root->data) free(root->data); + free(root); } -// Returns the number of entries in the tree given by root. unsigned int treeSize(const TreeNode *root) { - + if (root == NULL) return 0; + return 1 + treeSize(root->left) + treeSize(root->right); } \ No newline at end of file diff --git a/bintree.h b/bintree.h index 25e16b2..64da24b 100644 --- a/bintree.h +++ b/bintree.h @@ -3,6 +3,7 @@ #include +// Funktionszeiger für Vergleiche typedef int (*CompareFctType)(const void *arg1, const void *arg2); typedef struct node @@ -12,16 +13,16 @@ typedef struct node struct node *right; } TreeNode; -// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates -// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). +// Fügt Daten ein. Akzeptiert Duplikate, wenn isDuplicate NULL ist. TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate); -// Iterates over the tree given by root. Follows the usage of strtok. If tree is NULL, the next entry of the last tree given is returned in ordering direction. -// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element, -// push the top node and push all its left nodes. + +// Iteriert über den Baum (stateful mit internem Stack, wie strtok) void *nextTreeData(TreeNode *root); -// Releases all memory resources (including data copies). + +// Löscht den Baum und die Daten void clearTree(TreeNode *root); -// Returns the number of entries in the tree given by root. + +// Zählt Knoten unsigned int treeSize(const TreeNode *root); #endif \ No newline at end of file diff --git a/bintree.o b/bintree.o new file mode 100644 index 0000000000000000000000000000000000000000..c133e8db6cfe4afd6b17343996b946c48f2634e7 GIT binary patch literal 5878 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 l7x4?D5azv~H!X+f5&~gS7urYrE9i=KuYj$Gvms zCgHKJyZiZjKe=;Wzw>*a-#Pc(M=G}tGbdv#1?R*BV~3H_;p4y4|Ma6dXZ|xe?5Xr` zEjX-Id}~2%Yg>=EtGjbYcjHcPQ)5R*XVkkr;_dG3@V0e$%c^R;J3E^rMcLUI1rl{A zz*zHr9`@|ArETm{#!jc=WQ$m)!?A>22_OP=pe`4whj;R6lu#b^#5Wx}73c_|6*w+y z(jZp@3SM3<`ywxpsDv72jer}54l+cR|28nzKnhaFA@Hm6lcXcnj1^8&pZ^Kakt|Nq z%!;Csz9b;RP#2&5hAURDum*B*Ixt1@rJRHd@pz0ORSX58))4mg7t~ ze85oDCE&P>4QM2VuEUvd_z12~!2N{ib>Sp9G$bA<`ii#q^ibU>G|&1eXFvLhzczu7 z>v|Y4SvbqAus*^UZRhwr)HH&V=#xANhmXq}Y42>3wmF1Gf`cs*4A4EY7|yG4-ps3vA0NT3SjNk_q-O@Cr02c7%J}hdx+{5ktqX}q z!aZPs@Qjb(R<7pxIO*35IP!r{@haoTM{ui)dHH4fEe0IPagbLTKR$w6Blx>14b?ut z5&h2^AUxv(oVDhI(*G|Sc)q2j$UT1_7uP-C$NabWZ}!*uYwK>gxh6R9^ZLW&W|1Ai z7z@U_T*25Sf4+esdtKH5W2a`e3NKV-nR+uvDE#e?tQ}mKc?^P$jkC4Qd05wruDL}6W%8DWV*iJwUEact$gs5j$Y&g zufPXRo&l<-=c6W`0~rR7#8+R;*s$OmW3~`#|KfV(iSaAnotPLN#vmw!<6|)J_Wisa zC|Eqh(th$P@I7oEaD1BCPX2@s6d!xuY~s1P;NTm;SsWa!^c)MkOBhd;1Y>oc;E+CY zEve&3{C+Rep}-m78s=3;;|ozW7l3dV_;?h4CNea0=vg1NV3x(N#bU-R5&wpmB09g2WgE z1f7?zffo**2o4^NzXQvFG3s`5Jq?o~{ROlJ2Lq=C0-p={c<@+Y93TLFT_iNj5mEvE zI0ruxAA#)$17`;AIpf$B-*e9yim@{4e-`*af>-?C zOjO*5)gMee&Z1dLn#&g$_9g2MywG~o`Lu=a(|Tl%Gme#~%R zI8vqO6p`mBVi-g)fb4XVk4i5|Wgb#KA9W=8Dh31Iiowc4PRG6fi;(u|d=fcRh=XwFD+)OCzk%QKC^ER-b*h&-eMEKgOxbDF?BqG+<2?7Cz1K$*du4z# zh(d#x^EmK=&uUDv$*Dzxe}Is89f|KiKo;CO(2_4bhk{l<>;1Mev&D6JJX;cs>0fRE zDd6}9;W(y0j3ONz-H<*cTkj;#iRmAa#g7p1{!!(x+tAb`o0_NzQ3F*WSv8AS>3%Bm zF#&?GGtc@wz!RM#3Ly%a^JK47P7-j5@fgODJ|8VdA8thA{@(;JmAR*X%P8~3oLj(h zK{s6@b&GD-BY#R81_=xU9)b%g1QQi6wC80?!YhElEA)CK{%s&1d|uXYaz{|3ofsI^ zfT@tj2{odm(g7vL6ET9t2_gy%MVT{vN;uP#b{IG&PR&AbZGej81E+NE&=9!P)|E zCC1s|6oAr9bm;fO6%gIwD;LEAZzoKVahf9QULEud1m4E9=oyG>YXfh0?}c8@kQ|v9 z7V(?G$>3464h1I$#}p5BKZyl?VnszTz%V!(9LiFYFen_S_2;p`X=47=hvI2KCy?}d z2J6Nt*qC!RXGly&s}{$PD7s4*9JV@AA>M3#0w3E@epAuL0YaS zQZYacJ5nH{!7J_fW$?;}Nn(8cdkJGOgLMvQ$q2dzT?oTa-hDLUVwGrk*))eX*O<|y zE1cR)$~I*<&6h2xBO@oO5)H>=Z0*tBxs!AtZ$9N72%Le~`P__Wx*sF9$c(RpsF**o z$ibkHlC#>syiQ`d5BZN{|3l@t7 zXA%3c(5%7Zi`Asjn~RW0&0MTEuu6v5LNYT%8)(ZgZK@R(Qd&M^;Bh}hAQ{9+px7Lp z$0PVqVBCLr79dDrp9kg_1HYz73ES3<^SKj*`O2XV#1SN^$(R{P3FJ~F@uC%^tU^*$ zrH5Pr7dn|-mq94=)Lfd6Uw(67TnnZjRnVJfjg*4EOgxaUIo<2&k^WQUNeCW?Qfv40LUNHl`Mt%A$=3I3?3Ds=9{9P;?rps zZQ)@m8V3HjpYO%-@kt1dl8UjmrPW~FX)N@p@*zH1X3uWmB$rZ&0FL3p4qRXf41b6F z5V`oW{~%8EH^V5>l2hBaXoxHp*j-(C09=13|2qmvC3BwiGlGcV5A5xbbV7U?Riwj%VM--A4B_J z5Jl9`GHFe$atukaNN`7+0KzyqO@tK)482I#a>NZk4Mw*yK^cw+4^N9ax z8V`tT&!}oe~PC0K1|Ls(D--=7|M$; zC802)pp{*q#uZJIXS5yqdg3;rudi_<1uFs6Tw zYKQ2OgDxfVhN*~|_{Shs_`JAY=eumMUS893!r&M<180t|-TzY5J9vEHq!t{y_-JtP z@!(MO=o#9#n#c_foN@)%{<`-!xSak7jT>6>+V`W1=ZScsZfptf* zWj5M-`qUS#?J<4pHj3WSRO}9v!7ua;C}X+8PBsGh@Ul_M<;n2CJI-k4{#T-DlK+!m z#E94+v<7vEhFDswL`D`*&4o9h14 zZ-IOa3eJ1C2$Y*r_G0#(7&rME$EXg*KJ0p{%4?3ql zWzzi;mG3jlccOf<2gV@#1OB^IZZgY%N#z>ygrQ4*P5F&vIC*gS*U_A?%~nI`}=blw-@S5E~=$6_9_p zWms$zhk{Kj@7oGL`YnjKKQ@P!yD_~FHGyR>1qVj+VYGc@ZiEn4vG)0HOy(h1tlCws zjiKn?`%yIc2aaIS5WvhT)6U|cvsaPXLW-%kMmlna3pL*gHTM}F)KYJlqV ziVM&9-(epic1xC@Z&+ish*?_yk1Yg^aE8d3pFfe;iH$j$Z}!~-Y}oKC8w$NU@T1>H zT|=SKfggRXcjkcpHFTk?h!A#+X}@gXjKhD}2XL{fjv>O9xywd_vD$()LFXl(1bF%2 zcY}jBVu06pCh}510z>>CCi1><2NBO+0gGTVjAE7|`z`zJ$pvI8j62R;_V=$QzHud7 zmY*Nr%qP_B$501#$8SJ!IAL&spE|WcFBBi7DasdHsRP;m-$rKyhaxU;uC}^wd;XaI z(|R$U<1b_Dg?7nO`f+|82F7Lm`04n(EV9Z%Cs{srNfsrGUpS`!9lFs$u2UQw)W3{! z#o%~w@rmHTnY5353cs1|kMD=2V@{gFdmPA>rckz(vNbM@cK805k;e$ew$612pb7s! zLimY_wLk8@`(%jRbl@GAd*5roGVqSaz5h=D?RS4A!2Em0M?t)0|LC2m!EEfaO;ju% ztI&>PyE};GPj7w@O9t!=fBZJWe;w6Ab?^HwI=Szo0XFcC&%OU=V6HqC zV1fb37-u4#d};9eXqQw8fBa4Cr}_`m7K)_20F+7MkCOdy591bW<$fRf_--4yiu+?h zSlJjKa11{H;M-zzKbnn^;;9_`T`(4OO}sYnBAoO2!fRLN1L*EoPSW-;kC(Ar><#b# zzn}^u3?9q;6PJ5`7aEDBlUq4dKN^`Il1Le#+w9=eR7o}orXRPe_~MGSr`;d_1Db=h zRedi9T6^66u{Tkr)cglrVu~vqDQpRhb&^(zGJZk72El#8m_THuG#kbQPWQ)$iP*rI ze)j|SCD8Z`rvWW1g^s~vPZo0;q*(VrDvVtbTT+aBwZs_L^Pi+ZbXTnOOojGKXIgOZ zcW|5d=0tW;7vE3L58I5LY$9b1W&dO`Sdf=z@vpsuI)q0r8h($4%E5U2%Tza%y${9s z=a5%{)?5$N!-o6ofM)+_i+k3$qYE)>>?`O8|9pLh`yGf!wFQOl#kB>+m@LW)d=q1| zs;GayWjHvPU5>sd-$pnil(Y`@24gc~*j)JL;E_E)g!a69epgz$(d*v#ap1h}Q@D@4 zd*gL6B)b}Q%o8^ZoJrq(2ZH$s$&xg$Eqg`W{kR+Wp=#XqxgMG&N8YbdCZ@kx%gfOK zLNJ)}-Wr@3H}4T%r-P1r-xoo7_loN4^WNMepZjs%s323Fp^lCV-IL5VZHmg;Ei zBv4<7y7+OZ<>b%cPq3eHC)HaqwD4bQ$cKM8k@qOBfDmjyhjMWL_vy~UlIMBVbq^uo z{+l`Ruff3=CteF8tY>3JNe?1s1qXjc3(H%vY4`o!*MW*Fm*3kAPAqIiUokCsWBQH2 zy?=D@UxI_*>CM31EV3k~v}fq*Ox!DcI-RRJIQV>YMQ{)|cZXIMq0`_RqLSz2{OIpi z18DG9!NE)3;<-}HaSTnTo)G(Gk6ETC9~0}pnEp?I2KjIH=5X3rp^Eh-h`c0FPUMX= zlNPc+LuD*@S1)_z)I}C_Ws<>fL@&b9Bc`oA5sdjgy{Cd$fL z_h&Kv7dKId=)c7;hM7-&$Mnyb{t9pEZHei}k%LqBeg&p}3VAYhzFOB|aKVo8btC|c z`AfuwB(6ph~L|zT`C`Jz% zn5IbN^-E+C`gpLOljVRY4-bF;$JX^ft}phi#cgbNu<0h;#(sIvTDpxLb*c3{wcnYa z>2N`%q(x!H+T*=H#>I$yE&=Q8e~HI+=xgANYj+O9){2E#F3=tJ=q${xxE04Q zi^8|b>y%(qEBN^Oo_iR-?f!bpo_oM$@2gmB%xW39Cl%|QZF+w6g=N1LaYM}D!NGTE zA^N8v1Z#f@z^QTuUi)JA>!&^ieZ}&gE+E%y*>erl;;Cp_zYdF9zqq|`>ZQfMr;iB! z63ZK0v@U+Re5j1&2T({Ql|)PYLm_Bm)`QT-SfS}pLLWye29H7?xRPA^a`zL7`hetX ziT+FC=>nJ~;pu{C`rvUXe~TpV{z@=aRPN(W2Iv1B?)ZX#uuOI>2Z9Ri=$>n=c5T^n z7qNdDhFlLru2+V1&cJ4 z<{$Dy|0(^@|51zn*TWy7|550FJ@kL1J1aPFw6J{b%iJGh>kIyac6gNkSHv#)(q;Uz z2MWEGJfgCxbX}!(LU}|^1*zY7=0^F&Nq?-LmOpTXAArSBs^aez!QV@Pq4g70;BWI# zt(Ct`;O}_l;PLMCGB8-Nb`%#^oWWOme}t8 z2!XHdf9c*g%3{H+O6|MU!3-8Rg|NEj*M=1Z`Q3AadrtDwKspO9;W^&A`)9$$M}nxV z-;&Umu!#8x7ZBgXL{u?&EPgE_E7-zyBwbMA$&kUj@lXg~#$$t+rYMuR(cc#wx|=Rn z{~1@4SUR=RC2SX6!uC=3HF0{x0`pk>pP@lJau>A@yx=3`f*%7Pp9v>L`FFG$0?OE= zD4(QOiE=7_yOhvYUay%H;kGFdV%P6WSW_5Ev6W-`pclNvBnY41t9Mg+1PNUG0r`M!LNnjXNXPXRy|`9j!f0o!yb1q9}h`0oR*t z5$~?HNPEP)wXwB5(&6ptY^P*Li`y8%`Me65Y!fuR|>J370&BX>k4JYFGLShT9W#ak1(qqn0uQrNK=bXq9e z;l;0aVXrsT+d=S=?z_NLv7cRN7$BX33W-rRS*}|S{7d9)aK(C>KvyAT%(e9Gz6aAt* zniRK`UXoLP_m1A3kq&aRosDpyNOyNoV zq}f|ox4BGlQP*)tN9S%S9p^i|voYEVZVMOlflNcEr*PqptGx?%EcSW}yCczEjqTT= z09zb?d1B&joU?Eq#Q6ly=WsrNvl4pQy=3>Q5_*X%+O{*|ZE0+4@9mCUBaG;8ZU#p^ z-i2KlwmsgCPH)>zM2{ssk)~){X9x3oZ*J?3_BOWP)Enu(lXnL1EwI7DX7BbpqmdqO zW7OMdU{Urn`h~hXqrjzl?rw{=dYkYPnYXxaVIKp2C3{y-q_?>f%ENm=jYOMXM2mJd zb+&t9!yc+w*sMnMwEecXMPbLg5D83p;uh6*BH$jfclJif`rJvb_C_1KcSNGl9Gb57 z-ib)mOa&Ok3$6D8ahGDG>pK$@$>$5QuK2Zy3CjNwr_zhEf^bB0D5>^hpLIO>lFD87 zapS`h-8hollgs_pR{Y*1{3A)_{D-XYp``L?zqS4Gr1BS%$|Ff-mb5}l)6P-GUA|MlN3MM1BnEFK}LrJiU9HJqxde5)9Hj zoZFE1BE1@C1MdM0oG4hoDHJ*qrc$WwX%XApTxN4$6~ z6?sbMEP#HHr?lrX=mB|3J=my>B2Ou8TJ|IFLwXm^2axYa`WDWIkf-;a=i?kf-i!2d zoL@j5c4h&bk0TG;GkX2$3FOC+ejDduAC%Fg55?nk}>=_hbLfcyy3(>NbSp3>5l&@I6u zeF*0vf|w<${ee(enKACt*jI081fj~EP!(y`TyyM z1_m`xI`ce|Rh-$7(Ul%@ji!#Jj5|&g8Rm6dx;UvGHG`an4)TPZ5 z?UZudgr82AQ+HLTIJHnxJ~Jhf=}bN9DAqz#!lXEK>dD)eC*bH#$S2k((oyx9DGNbo zy+LPYLf^kl$WPWcnfLAlc$HT?W~S(w+B`-OoZkl}Y-UO?=>N!|ulf=0RT3$vV&*|AKEj^kx zrjI*MgHNLSh@_=En7&*q)-qCA#`4r+y&}+s!ar>+K7T8j-&2)LR|yuPM~f)q3$`8j zKf_%55aMw{-8$5bqHa8)t`&8sQFkVx?jh8e$@D>)J|WW=WjZF)6EYo_>6$$c|$ zpPIM>hlgZXPqaHqk3wrK9PSE-BOSZiy0KNq@>#ei5)F4mc8BRRO>8cMp!};k^H@uF zB*NH5j5Z@Xo9Ht);ik@x7Hsjic1IeUY0s@aLbZgVw=& z8ffH(l%0{COy^9Da|dcaeHTXl+`oAEwqfC;6|zCM&hrnb9)#!E1H-?NZ5qiAEajH z6y+9CNlwKjIMr&w37$bFtXplN3pW^2mfb`4`+rd$VAJ|S{2%>SWWwDS&Jjj=H8 z{jMruTNns6-N7zlAMPP}=QHeiHZ!(>^@z+cJnkIM8w1sw0~ITl7d5v-M~uxvpT@4X zB|CeT>~8B=0(~uke_`V`x}<&Cl4VPZC19Z)F2SZ&*mZzSJd^OZMjE>;9YS{8!mlk* zxGuHBk+)l*`T#>`5=~fg7yQ%$${qmRg`7#a<<_tj_Xu#G%bA3WJ76NFr+_Ea(f)qoGNmvD@9jr5NU zkBp2UAL4(k|B;bL9)IM}BZnUu`{MW)Pk)g;>Uq@rXz`=IM?;S`JlgeW|D(f?jy!tk z(a}f89vy%5^rP%C&tu-liXZbm7J97Vv98DZAM5+l=$DRviO_#={Lj?D)nLoPS;K?q zIIwr`qkWqWQOWBPe+2vwQgAiRtFe#I;a^PzO2`X%Uz&o)K0b%v;7kBY$O`zwnF=0z z_Z&WZTKH~{g2z5Shwo3onV1#$e>FqFV}GB+zXXXUI|Tf<<|=q^iGW`|88GVT)`Elm z#(FuD^F&+fKx)v?E*}^LvX+5o2 zT;iFYM6eW{H>L<^kx#RLWPFtfX)dFZlXtpOnmc>9%tv-V?@G*SXf#j?Mwx2ql3s?i8baph1geUwb&KO83ITd2$JiFS6?Vma2$ z^h_5aNbAA#3sG6+N^QdRT{I$}5MwF2+mFydry!IKx#R`WQQq*+WE74Z91ll8XLEFPt^EStU z`m7uomVH1#hl4-1$8MZKLOBmSaWAf{{Zg(EfhU%d4F#moK+PwAROZ(5Q*j5EtFa4h zbZ7^6lNyyw`HRS*NRxCOnZJ&tfg-cMD!X07JE5+PUCOCD4z%N9zKw(tR1kf*y;KOP zmp!zDI-cO!*%hs&Pb0f75h`X+2_H)r6k2g#n#KY=>?C?-T!4rD z5}4_|isW_CF`_6v%ta5Qg)wVgesvExbxi4Sj%0^(OzLnB;c!R{hjS!3T&ByB>~apn zX%@>9}1&!H$NrYMT-k(MY+$(l(` zF1;H;8^vs1^stn@R9lOkO>Web94A%GID((lHtg;-MmxKOU%PUDi^_Coali1o6!N_^ zaz{sQ7B$U)`8CS0H1cZ4>@<@23Zr&r!XR|!w1og)D4Gr z@W+64c6WA0*=<))9&w$eyaKuMxB#Rprq!n6NgLj=N%TX4Yby7qP28Cr2O8LH(p?2v zSS!iKLqQzpMu8GIzeYH*mO)%9xr_?n$;q9iWQD*8A0(U2!J?|RQ^=N)Nlj`rK13G9 zp&b;mWz3h%iGZ51jGPgHffu=AGp?tg=s4hUV)s@$Gt0PzUW0NR$al8&n2WNE)+}D@ zO{Hzu`RU~0m>l!}PR7D75@j4l)XB~j)EiLw4>IobBh9*ixbs68_sckwudf;?rAel~kgH-(JEb>ujQe?_LNtMaL>FjHK9-MMqPKPe8 zEohq6lLC%2&AkmKNomB7o6OORjAs0>l)F&&%n$*`neO>p6w|m)CF1&<)XaI!v|Os( zkV7c(h#nu!be%xpL44!8snUXY(YR&BS^+-fQV&%VbsU>`zGITxsBN z7Dzj~*@D@Ea2ZQ)l3M!{Q?`{-wuba}*@)Xk{BV2-*Ak*@$PtYo1g(}uS`N*T;j5gk zE41`18VxE|nA1gSBTFx!@j<58&eB(iyvwnx5$kh-yxp;DJIj;>sF)7}teF0wV;o;V zm<3wkTEUXddX$p&eu= zuoXuO){kMqpLYT3|1`X=5ohwo*$>E^a^lFQ>&Ogq_UJ?Ly_!9;pC)7pOV{KH;zH&I z!s%9e@63He4rHrsFQPub+;4Cmk8)*Ci zi_}kPp0A_)rv&{FK|i2KuoOa^MJ>cV-DKBWIV*odAe?4eCM@}8KkanQ7cEq zTd8jcJwu^4q!YqlQ8O2Y6sM7uIeuDT>Njv5xG{FQTKNyVh?~&x1H}5hsdzq}d*Wj1 zjzc?`leCA~iO1PF$X^HufY7&^^e);A>s&y@F(Wuy+OX;R;Y?y2n^Nh2Avm&%vm59;R_=`X$QLzh#cG78#@qr zx6BZ%1QCzB+q$q3uvOOh9Ju{YySumY3g-drr?t0rL~dzoh6vl-qrl}n@YKBmQ%x7P zgW2tT7}0(l=e!|La9*E&MlzvhW^mrZ|KR6@2eTo(}EcYv5bw z!*}zgQh~V?w>Mw)7Jjk1;Tvq5H@?hE9?n8&79XkyLM$g~&v+$XO5hf9lSksv4t^35 zUs!0R)k3SKg<8{(%1*C}KG0)tOAC~AZ4PyI9vJ&b`Y{ReIR(O5z9E;q4i{x&qp=2$ z>-%I?eR`UdH7vVu*2}ztbstso!1P6s;DM=`U4o~Hn(#ViG*TlX*wQRg8eY2KGSyHY z9NNKOq7T>7(#wRF#5Uy8>xGtFY?fHY84fN2-GVtp9Pe{*bfyieXmaENEm$LL;L=45 zU9etwqR{*0hTdn%b&`cZ8yqc{bF5~`TLi=4_&Y=bd(g{RZZS;@7$;O*&T`j_BKDvu z7%yXa7ZEJ!lvgar#+InSl9In6%JR8G(uQiv<&X!DJ^?r8_S;?1%_q^>xLbucGw|RS zV-$|G{<~%fxNg9m*S09``|!Ui+z(P`OGoDtyjzV|Y?ribr#I60Lm+M2cQiGj295j@ zd zt3YQPy|_m=&G6`1b6XSK;O9{IRoXw{Ynxg<+G^`I2f{U_!9ZCZZX_kth5XgE<^GCr zbzoz-ED#Fd-QLZmTd<%td({NOQ$RVUhT0GcmsV}Y>&mq?iFln;_m~Vk#RM-4)YOJI z_$$B-_zZ8Tst#|gC}p|{QG=$MP(^ty2~)#T%@)P}h6?{iE@@4zzoLSrnGls#H`g;) zLOD=bRlOx#Szc4=uPqIRMTc|~U_%|Kl~#tr{>^3K_0|5(09vt}WlRr&2iY>Ghp4F{ zCTmz$5}3cDE`b!wPHG1Kycu9DC#lWaHC!2}WbU(qgv%={@&5u1FW~YfVX7_Z$ z<+kQoW-}?jBH%}#JhL){kEfG#FdUn0RuldTxG-AT9J9Kts&2ii&Nr(SbXADWHER_x zYUi1?A%9u8CRkMszpUF_T3cSVnO$UUtq#=IRd23g7n{`^s_Lr4o9f^>73G!Xwd@kJ z$zOr@|HHNA8-umsimIwm4ZGBAgk#j+;;)7v)qxEG_#~-qePDB7LwP9%Fq?0JR+NUM z!+Ooi>HxT{tST$tu!Su!t4WjPn@h_ArR*}ZwtRDKU}K;~gccDpVWx zZ>(blW|jZus`4^23Ll#Ova)Kn&}^;2M+@Lmbrs}SE0%L7Tr@@V8g_-*BGAIB;i?cu z8V&nW?kt5SjI>!zZ8dZP6D>BIxU#ClH*T)FWixy=M55HJhjyxJ*0U>3I1F^I{Q&9c zX2cPW3%affD_6wlCQNuzTa7=sfn9B_E3K$4V@s@c>uXt&StA6p2D0^)tPRxHhSwCYShJcK zL%`i!Tf^3x%^TtC)ncZq35!@?4zaE=A*ix$v$A7F6&xOpT3(6KaqU!4@C1x01-8x# z7V?+g2#=8dMVc}oud_ndZV3e{0ySWa@YS&Et}G;m=|bVme)g38_jm2yU|}8ghH0nj9r7TQ5){g z2VAMYmeeI%%dM@lYl-N($=X;WyUNxZt*x@_8qu}F+Niq9)=INg2()bZnhllyaA^=9 zcBx^Tlbe^XT$RvVmE62?+46+uklB3m^0EzxSY>s5Vi8flIvhk`4VAH*OgM6SxK3#) zX3{_yQ`+XTn_0El?!UPnEKD^nYNi3S4vktHWWrjj&e8~t7~|w-OAB$L#@a2m7NJkL zUN{t}u4MHV04OSPb+^URNO*bNrXf}yD1~EfwE+luOo&@85QIMo#Wov2GK$-55Vf}? z&KS3w?Q#imOL=WD3?s6z+2pUd#lNKni(9O`!&q-(CAnrb{)f2f{5*owqy+P_Mzf(N zSiYfl8QX5wYz@$qRbLA?2n$-9%UF}yjv1}83Ik9EZJLttOoc&dgC7%y7@RC(RwpbT z!nahH*9KUN*~qn4xh#Bhxj&5Pw!>`MTt%}_$X{OVhhwr9Rwtt=sI4Vl9V3 zK@C4^bj7N(-E5LllaAR=vs!p^MU`BL*02tj9u z)@iMT*u|{NtRrDX*re%@eb{U<{F*{4R$A2DZ8poR2WY*lTnu)s?Qq#t>%S4!?m0Uk zQ5L{a6IkelyAy6F8U|MOzey@*m)XR_c1>+5+ilj7^wp)+tk0~ffQzs@nYiYpXEQC= zoIllS@MHyt_E+PYh!$(sa)`7kFEAwtuUfMn*W<(|udJsrBCZyBd40_-{ty$_gS>*X zq0=S2d{&b`bLsHl&MvNx5rUY*lcw^<6P>tjP6=??ixH$ z?tvIcX3S2g$IS>s0G$L7?B^!1FQvl$6QhztlBl?aW^|YG6F%%ZO)vawPfc>(4QP2Y01=u>$t4$l`f&g&?28tls#iA6J!dFXC+%A+iHTG zJdIFtcV7e{J;{S$h8R_*lXLYeCs#u^!G5z0sSGD4>`88(D8uX`3_Lad6C36jsFH>T z27wyRhFMJaoHqVgm78j_V44^S6g+^3MuHJ_QYh+p)Cf;k9AqSODU_p}dvd#FO=Y)i zq3;}FKDTKe51D61vU#Ski;A6w2`Km|V?nYGml-@w%NWpPu*A@lXdvZ(cOiCJf{NV$ zQ^}ZOHG*!0MQLUVi?(SY(J>My2SiuZlrTu`%$UPAVUXI)pPD>u%|U9>j&h2mS<7?^ ztB9H4#~N|7R`c0PnOho%I}1%(N+doola21tG%;jnEC7m*`GvOk8BOq!I#mFs;zaheQ;?9$VV^?9zPdX8(0?#6=O;nn9-Qm@ae)w6c$+I1h&)85e2cj+^Js;5Ww%a`ie zu66olbZs!9&qJbZ($n|r+DM3Li9T+wvVb$Z?jy!dpvK6f8TzT_y#)6-qM zp55}So_VXDM?g`1=5u=1Zt&sAoDC`h^ zgo@PL2Xpl+eyzJ+(>=TO+}0=ctY>xY#yfP^v%05um##l6Dn6vU22i2T*rjW|%k|7> z^%+a`nZMGt-3}Mn_$07SZ^qvNVkvGC3p2LS?PB_uee53kp(ixN^B|w0+#~eE&8QxP zc4lb0%hjtd27j*!wMJ9x^|`5A^*KV3vwHQcsD9BFJv*w;ah2%#VEj2f+j-}(KI>Wi z3Ih6q?)jWv@Cn@=1+H0o!47@)UVRp|xSrA7pVJra(C6$GI!8s;U+Rl@>lf|ijzSRg z{*vmn8}+qqdgib7nM-vK?^~qjKre@Nt#7~XdQMO8)#t#Io^&nKU4k{w7JcDvJrC|D zjh@-7d;Ugu?bR1=(bM7Va%SJ*#0(LD>uF;R!yzZbgno=%*7u+MSdepd5d6 z=#!MwS7CgqXEEpLGk<+RcO4K~+6$Ywz!Z%wJjhe8XQ7~N0oPB8x)#)31*5H6r(d;+ zB+e&DGNl`}=>z)AUOf|DCnU;*{);J#_QgCELlVL+rQ$RCY)aPY9-ltfv1FE>wN9UT zBL=!xpSeZPckbGx&ur0kr@LOiyP?iv%rB z5|V}a;JnU}iXk`*OVJQqfpqe?@I6@1lOiqc+=Lvfrk}0&5yMSAujyQ*kr&P&YW2Fd zqfehdApA=jVy`HDN6!)r&BAy}Yti#=)aN2reS^G@c%pw|GksY2JZOIxr|>>LLC>dI z`YQZrE9r;+;~(2dxe)#Eu%I4mapr3JMZX@<^Y`h62*ptf%S(3X^I>-w6egbQN45* zH?)S~x&T9XKGiy|o~gT?eNlY{m0X|I)16tvy7t^7`o*prsVdb~r01oo5l`S0I5El0 zc=E|7b@!9{B4Ax7%qhLNMNB0{`X$flx~tgrn&X;W%m^pQD=>RqkKawMU+XgvsW*T` z$}58SCgh!%TC~)=?$c*J%jH;rY0Onj`p7QUuRXx2*7x?be z^#MKi4PASZ2aS4YoXkc~?M&`UTVRUAIJwyzKO@8NA4CTA%#ZVJrd@W~jxEK#H}2R` zd|kz5mpL?GE0ehC#komwJMYGmIp4?mN1Pmg%9Yr7(Msq+oogw#k$%wqgX4d{24+D7 z`t~$jqtBa_=Hd$#)D=k4)H;q_k`8~4=RQYicB-T1ML?Ty$!`f8aCZo}649N$0qrB- zQ7>h4IDbz5fU_*8UkhZVdYzxqp7*~vGYwY=IHu!o1np`OMei)oVbI-Z@;8F|p~2J^g{ zA=QJQM*nJ4Zh}jG2GxM;w!$Sp`f9*!w!$Sp_N(BqfaieZFGP35Ykl@r!8s(|5($_5 zd^LxYelRS?Yn2$U*<@a>Kf<5-sBcm5N03?RHB0#;zVu4l(w^?7 zrFh79iTJk@OWXM)ze~keA(ytTShH$d)15o;F~6c3^xJ0i+tw%kxy7=T%Zn5K!$mKB z@~=A@-nDE6|8Ezf!#0zE>WBYDvt%cpG2Xpm`8Gk5(Q8cp8t?L=lBqt+GpXz!RN~wB z*KDi9w?%rkMOyIP&TXCeC=WhS7}R;={|13f z%4SXo*UIP}4-9`8Nwp;iN^kCT?6_b9Du;Ogz15^_=FUx0a$N{4JeU~2kTLpx4^G8x zVtT<=YgM0D`fu>mMB0gY({?JPBzmiKQX?qAX#bT{-ucbM?ERXF&w(v5XD=6qHB_|p z+*So*`H{Hnm}I(;tAexhLKB$DLDG5#E04s*3^VzrwGBLb$M*Im^g>e)@@C`zvPDG^ ze@7GluLgYoaf0EgK?LGRAI%V!qfwSL=EdV+mL{XH2RS@Qg}oub@Y+w{cMRJ|RKk1N zyp1>D2NzlVIE>%%v%vfSFj(y4+u#Bht^<)Po~9Q*3f%<|&X4HDzx#$7FHWNdUk}IA z2u2N+=!Hq*)TA{JH4WJFnobJZ)EJ$HAHq!EF&aJ#%mKiRoCSuy7j@_?Fh2wgi7*|{ z^p1G{Szs=PnL=lgeK}x?&jPavFyq*!oQ|JefbpG$pFabP_bjvy0mgF{m=^)le-@Y@ z5I<*u`5j=`Szz1{`t(`kS_qh~v*5W7Fk?7rd=Xj3s!)2B*O0M`+VL&_=H2XPMh(Gi zLFqKFpm;WT*dmVa@d?o|j{MW~4qG8_cs)bh}F123zeBK{#9 zQ6lapixNfKd+1g&KcEo66v&d96!n>i;4pw`z;A{LfLu|R2?Is|L)+PS$ui+kk*yYW zGP2#dgDy7cBbP&>egPk?!NQkbnA z2VtfR{uPt(9}6B1V(3uNA|28fhv$n%`TL&fu-o(&unt;Y8%Ijdt!Ni|F0k-I1*K>5 zD4}P9Nv9^u@dOdUK|9z^jlPwf#mk95hb0WPI5qxcKw>k`zbIkI_njJfi5T^Xfd49C zX!p&j(RV4WBZXjpC}C)Bc53uJOZ!1zjulQY{&Bv-bO#^(Ecrx!UzyG zmIXf~*Q;o->iIqMLmAl~00rS=w2Nsyl#lhH8mxmKvb)`X$j8XDgpX|p!`A3WSjor8 zvxJZNEt;lwI>^U}!r6R`JWKc({R1l~H0hv^QPDwMI5iK?C;yNilJ`-oQ~Q_XW?m*g z96tv?909cO!^6l~W1{lIBWMwRs4mo+P-7nR!86IuV=u2>f*KkHc8~fTZ&x22EWn^A z80#GOmj>$9z;lO$!Clvcxe zG8g8(R*iBz(tAnY!h31Hu^!5MA4fIB13&h8nR<}-`k-gwy?p>BTUrnDUizx4@ZL{b zw5TA-dmB(VoA=V!RE76`204PZ9^}2`mBM@N?F3EUODk{Tz4Wya`$67Y4Amil?4@=9 z)KC` z{FXZ+iHKX4i)SQM0c2D>zb>PPXfXM)9 zJB(;o-Xidj#`@6!krIvz^A-?JI+VBMLsH=_`AHDwn#~0m!r;^hCP`y*edq-Y3;-Ci zk^P{kMgM6+cocoD$0`@~AdjLi8;Yn!&x+a)@~BZ%pUtD_i-y9Z9s;zLXTnMzMPEY{ z9`$vqvK{16W9Q&ebkAFOR4Z^;b*(&#J_ag0DsfxXB>5?H3!zAyf-H_Npr%WDi*>F{ z11@nq2bg1%!lWB8F9YU!1ZVO(E1paPW*jgFB#d>=%{E|u378S6%kI7EGg*kwfSH2} zIy($~qgou9uuRX)$zXB~n0bKlU@Erb5jfOH5&9voqyIrtq)71ed`60)dGXIYta#+y zT@3EP7HDm=v{OON-Cn?e5x_Ly*E*t#U?)U`i*2q4|9cPC1$&7hyCHHJSow5u*t^&68Y=UkRCf)A&zUQL%v(gIA8Yb?DWv zdhzznsG$#S37#opnX0CK;jp}3hg!I=@?LkKM+0(VEGu6X{E+Pbjy9Mz;jsIvl@@`j z{htQpIcAMK&3dS){s7nn6QE`FL4sDk+7B4vs|BdFt^t&uD-At&G)DQ}m$|pCa|<4f*qbpb}mWnXJ3e(DTbHhBpBfvJi=IzDO=E2TE!To|9VRQf729R`9|?M_=XqQ&t0xbc$T)H z-G8}eYwzjl?J~I$?C*xqf}hE4K~VPrCS)1QpG3_V&Z#3nUvsz-|3^qgHpB$fU^8ai zs3FWx5FP`wT|b`(3_uc&^RfE~`U$(!NV6U)CeUsMQE+NtBk52v;SgYi-3tJb6cb9T zYYXZt%8o0!lI}?n$|3<%IyxPUoCo`1bfMKCdM3%v@sw>fbU0bu5HNm2^Hai9Y#p=k zL!6q2_Q7h~22=BQ<@ef(d#JV zTtD7P*HJ|J7+`#}#X3{068;S}uPW*cPKbZW-PCi!sG(jb0doki@tUhsCzu_xz~rFD zgLA4mj_}-ocJDMWcCBs)<*TTxaVQTz7p)o`PO_h%uB5zh62bGW(69ASvmSXb7=c!a zs`XH_-Z)@{hZg_<;UM8qtDUzD3nu)7_5?3)hi*c+P@C$Cl~C>l%s5gcoNw_&!?5aQ z+}9I$i029e5*dD+j}FJtgVUO9W|R>i1;b6~XOdO7Tn!S8&<{lk!e|~!Kkpd&>5KM7 zCtnSYa7jrnv%kunk6fqGNytT9Sr5fe26z?`8+WYLznV|5*JD5+_?bRpn>>FNTu&ac z&&8kN7-zMG$FK#hAFPM+`F!rDl$8Z_(gqxWuLgK`{-dnylP!}*l5^39jDA7G${v%5%&E~-Z&-Qi z=tp>jm9aPtw{$HlHqDG8J~)^rD)qYdy#}=wD|D-yr>u;>F`sA4#kzG+zhZ>X`Y`B zVYsA2U1`$p9F2xaXFYl4`vrp^dMPlxOa3=0&W|bxekPA~cDt_t#U%fcu_Yv1Cgn%Q z=V^JCv+x5zPovYRk!7uinuX(lA!igoXm&mTGm*|W|;_J1>ECuR>I zI$Doj)Qn6cduLa)t+S(tKYKtDI}L4!UZf2|YE_$E8#cnmJ*jhv0M8lPAX{4x6#??k zK^s4}XyauYQ%|Ah&^c(M0W4UxA$m=(4Wrj&`z_}Y4{0omaWS`gC=#kf~7aL zrn*9G<^NxhF;j;v(bnFMJ8)Olq$PDYtfa68BkmG5n@$FEE)hvsdHL(W%C*X`Mj=4L zAw9uv_e9^2veWx!Q^~HP&HE@c7^JjVGG6J=OB}8MP|HR*Oy3&+Be;ggT6w~;;$+L=w2|P>LAD%{bW40fda;fAn2q|Vjk?PmaZ>if7eu|pM*W11I<3B} znxAQ-K6*ja*Vw3!+o;p}$4dQTle!#nk4`hf;wgJ#M2;@7q~r zZ?#e1XQLj!AnHH2QSY}=@3K*U&_@0A1yMh3qkg}QdY_H@6E^B+E{OWuHtNGR>istA zFWRWHE5vTZ`CZ4Iu~C26M*V&p^)VZD*9B33*G7HBMt#^u{e+FW=Ypuy?I)m0xQ2b) zM*U$M^>G{Z{0pLI)f|_=vy`1;)Ks#oIqrRwtK@NIuc_y+m4}s;r-oVWQof;ip(*QOlk2=@nSHhq zM_+w`Q<t~sadrz)u@r)QmDM;yr|!AqkhIlJ#M4^ppAO*1yO&%Mx7~JsM);a zw2k_Rjry7kqCRY+P9xW%=aMrv>VIXU?zmBk3K!D3W&GoyWrMQv)G(``Q@){HmTU@Rx6qL5yjBnJ6#2w&F4)il+PzfDt&%fN%21TeBU|vyveij`2?P&>|dWocIET$ zqg*8?l)a|*=aq3~<*8v-Hz?nj#^(*W&dcjc6lTNck1KvuP03*;g{oP#+2(cMo<{R3 z(wcab*Co)BUN`bSdR_B5c%8|!^11|`rPsx$kzIM+`zTk*sIu489<_2zS$S%h)oYY* zOm|;K+3UQ#E=yrn9<}nY;z!k#Jg%frHLKRxyzaNtXkK}piAQ-|0xjuvhm;hcnS8w0 z^E*8kmxfckT@JAm4(Vfd*%S36y^iiCPZj5t*S(K&mC(~`Lar(A^sO9KR-VS|Jjyq; z1qqrFS({wv<#n%{_jlyg#IWK=`B+K6l0wz2$}+u9ddp$uE$2mj+(!Lj8}<8b)GxMC zAH5*zKe16Cu~8qkQD0=Ee*A){$8FRfw^4uCM!m?SE`7de8lP9=-L#+@?+I3x793Mj zfM)XXUXOSBHenjh>BhUsvzlcRc$Tu4P9wV-7w@B7B_qmSQ;+49hm@74hFSe{{tA#nvyOhg{oQgu6kmDsi);{nnv@=>r6b#>k?>5uN!|Ky{_;a zyw2oVd0hg}((78LkzIM+`zTjQpR(7~9<}m*W#y@1R@3v%VpJ|l4gkhgq#@UNdENaA zv+}5wU5X!7Q_`TMP&KRGvUy!}8qF)OGw~>|OQ0pa?)3ZUb@aWQv&A}-XXSMXJWH?J zJB{qh>)uDXN?Mh@ruL|neagyH!>oQl`Nm||aZ>h|4cX1-(3=u`v0uQ7^Pn-)E!ly&&q_Y}AWw z)V((9tv2d~7eu|@M!nERJ>N#X-bTInf~eQpsC#YHJvQn-8}&68L_K7qo^PY>vQaNI zsmo~m@2HvTDqGFMCLT2lC(x2n%crCO&E!K}aTt+gGMMDJIvI?7-k9*8Z5B3pRFl5I+HB*|d*wKjIMd_H%3`C0+rDMx#k0Ruqx4V2Vf zPFhbe_8rtHdx@I2P^0bwiyC?os$be&)XYH*9aIuEi%>&Pj|hIKZ6#{deFp(U?F!H*Wp}e?H*M0YH?#9*U#2^6<~j4;ZZ=rh4~8h% zkW#^XkuEA2N)16O)YcE{2O;%CO$BYf2$5nDw6yrCN;Uq@J@?O?dHdehrGMW1-nr+V zbM86ko_lBBom)WoKJ_SQV8fJ7%cMJ@zW2NFlR-NdFdsU1U)u01Kn^<2D&iw%_6W;= z9W*K0=WX}|Xz1htZ=Vh!T2m|G(?H%AV{rkAP0rTav-Ck)enGN26Hd-6(Acz z=3h}OBOP;o9moOrkC*uaAlIFpK^%Mx$B?WGt9}m12EOrqJq*OIZkY2|fxz$;&QAmR zoAXtC6+8pvhCrSNazM!Z3Xl$HiK~$r$hwx$B5wiNbP|S(CJKZWABELN91Zn82E_NS z6i#_8sY%R*jPk4mt+qIM^^Dq3xVMq2*&K<3bzEv8#xQsLiikzVxoAJFVUN8al`3)ej%Jp5iD zFF8Kc>I4w{QyGi%xZH4jbmT5$bcBSLsfnW@KEDQHpW9)1-T`t=^!{%kmxWb#;GEY} z&NGS6E+C|kuP(j>#IC8C^GP5#1?MFolVU8+0T~rD+Veo{6K=N!OL-^G(A6EH)eE56 z0Lpg8hu}>h=*q}b8V6bz*7%2MMbfc^9{{nx^F?1#nwK#$ziWk3LRZTpqWAl8qOGr* zsP~6~Q1>j4t{4#)*PZ_;Dw#|+CVK9D60Ht8J7WaN#exmjJ5fFb8ec8zhzsk{bOtnY zLc;SvCLL$u^BfTAt1khuJ2|@ci>S)=K2NP)1I;zT=Oz$}Z$Iw;0wQzfojAJ}jSP)i zqLWpT{eZv~jqW=^GbcFT2jrsA;t?QwU{d167MlUmadrkAoB}c;kOGLkr@*a#24qxl z{sr-IqeFb&0CK{~qen18GzprwL32v*`6m#{b$8%j?&}s1`@4Qd?!*y{cDI?4M}VAi zeNpd6f$R}lC?FRFk^=cDXuS>30a+Kwvq0=G4!EyPqQOUR!y7>Coj#1ac@M%x!RL0I zYIeeDs_2DM`}YPHwP#vQM?iC3NO(68dhXQsbw7~Pf@T~D{dxa+vJXjtyeC?n1u}Y1 zweCF+1i@0V#*cv95V7+DkjsM4%hXDY>F|U>r--W6`aNY&v zl0Y5=@}6jQ2*?3vRm6Krsf~ZpJZk*s1ZYNu4O>7Cx>h7v3FM}$nvk?2B>v!%(ESqi zCGzSOAnywaUjcH5K;8uMeei++MxNVoB%-v~ZXg??)m|Vk3xA%agA|1p-vA=BL>mbI z#?b114v0N}1KAkwLj;##Q|SIIXhtxCUc%o1*#sR-4VnLdtFdOh*lVc}lRzsj?PZcJ z<@R&9xLCw1_9{)X*nVCr!nV7>5LujP@FwMgUY~<^3a{c|qLnaBnsex-9e3km5+zF- z)AwC^zYZ33^Yq^3UMJvVknb5Q;-yZv7*h)GrAbzZoBm$u@!O6F#N9YJ9hNGhchL7U zZLVc{ZB7R!DXMoDL%2md%)(aO#DTeeEm~O*CkI8bK1|D=Hr+>Mw9V5dXglsy>OpkW zd)h6VMc!3Qc@e>s`VgRs_SSq%2&q2|UD?YA(M`3X;iDlY?g3pvdDUI(^ncG2Q@xcb zyZgA!OwAs7Tusf+FC3blRuhd!j~`JphZZIq$By;Us#cmW>NQ80#x!(2xMAH8x_I6S z4f|+KlJ3KsxqYWl-&efz*Uz42`8sM2fD9f_vYDFin%9S~!jptkD}}dMsUmJAC7fSz z*f7|PYjBcb*KxMjUPO45r}I_*_#pzb7Qxjxb@6C)IeYf34ONyUO5?CV2qFkfKA`Bu zVPZvy_~9?YW^*B5pgfb|G(Gw-fg_Ou-BiQyg-%$+QyF%Yq9R5JTG>$Z%U zgp2Mt#c|1>7cgN$SG=^CKe_kkRk=;EJ$64Q;TBBuU-keQ9+^SI3UeE=)B5voHl`K=+L@i9uyXmCQ zJW0F5$Ior~4S!XAeaQVJDvtP6kJ01_ulCtn9Zs_5T*C}-ATJ+Xo27Z#TKq`dHFSsb z;!v}R!^+8hc{u!+<2jt8#;I{8M)#nZYgGE4DrfV|`q@-A-YbeY>uLhWH^zH;6%-~f z#o@z6Sgc_xZzFIO&EX-X%4U))eQc|;hg9n0J%^q>kM75jwNk0Kt)y{*VgSYv37qa%|d z&j8WcE?jaU%+d8kC6nP@J7Lpz5q1*QF4bz1DLRiB=3arPs`LT%fZBuUb3X1K&ra)l zui3B_)ZrvW_b|S#@?@Rk3nG?|LJIc)Dxz{VQUOrFwunNPb=tlkiI6k9 zu!}BD6_N(mrmnh!+fRpO7l}zHX;QA#iL+$WRK(w+f`JjSr%W3nVFX>`Kn0~Dn z7i-ngq`_MWV2W%hX(1iM!E`KO+51OY_SxuE~%x{cR3f*6268c-?QO}-s#qY6NUD=l)|$V zbu*}ORd(ViSxO@3x7hVW=8+&LD;VIoa5Td+Obxt;B&0^-@Y3@eEi!)QD>Si*X zAGs95jDX-;wTY*VSp;eh&jos=i(K5lW*8hmGmEbJ7gK~0-`u6&u5hS@G$%o4JiC}SHGv)ZYE~ca`@L?GCfzkR*w(f*f4HF=&O)am zJOA1Cq8h8U_hk>LDQjA>&6ur3QHoj3j~N?2GIUOPnTmYy>(jRFhKSAQwGsmp*s_sz zYsaQ>M-d;N0aZxzZ;~&nrCvr=OpO=(fyx!*A5kSis1H97Jfr$?@LJl{C{=}iH;iMz z+!U-CxK^Ol;(42Fh-n_RM>l9M0hB@N9jxDmhtBfhTlSHyEtMPVDW4A!foIz7^4Wi&i z0ONIRL#)14jo>VA=2S`z1I%MH9LZg;O=!s7YR^8Crt5y9<_E_HyF)!(olupoL`84A zGgdS=iffe=2hrvuZT6;Ni`RW*FMD^8a{1}yvb&76Gwf8$_h#2Y3{4d*8(|!7!ug^Js`Z;}*FV!$gk1t~EAxZgIq~MGeB(1V(A7dQ`W25s` zJ%Yk!-6tZ+L?KavyB8T{-BXd?e7;l`F0HuqR|z*-uCNEPhKh1Oe`w|VH$y#LVd~M@snKA6=(DMt z@zCn2PnzS!%kdBXW9&MQ2QGW;%Qr*Erf!BFyL2PDnqm!%Eoo^V9z>_48$_VU)kr&vBXrNAxzTI_(XcyP<%pI(qBx@3Gp>W zUI)oB*ofq{E3vDs;Eq3e6;56Ax=_4ayoSkpxj21kW(lAE;8u|WsiILbkO#(N*T=iA zjvu)Sjg8RQRlMZ(0Xo@%@vfPU@!0hEk!i^9Ba7g~iwBl%9q*b((XNV>V8ir*WwvMk zOB7#;eL?y^d6L48m4@~hArXOv;^AfXuD5ADbQa&gP`WO@L}%FqyEPX3f{#7-Md0}g zIa!CleGZ`=eL@duRBizijStIC(JtUl2-*eYtW4h{UY_4u$nTEvsOxxRRB4%s6)(YS zPuKtL(M9M$ER|XEZgwNV{3;)+E8;fhD20rG_LJ|NQ;A!quyQ_=cQaN-`wT%`9`uPI zU%(_y*l)Vnpl>*6`hRJ(12b30dW9itM=3+1^6&Aha?2LCSlsTk_t|m#kiEx##D3I{*@xJg z<*OsB^J^;Evyxbzm&LQF+sj*5=WP_LlQ!z7*z)}Lkey69BqQ>UHd1!gQ=J4!OEBAv|)*fJZ=u!dGJwqq&J!25yt8OyZ=&cvU4;m_JWL$#`{uJZWHI8kZ_8 zx>_2MdR7^Sa*2s$3b|((uQC4-?Wzf440>`zzmpZCzJ1802lP7okUK`ee?ZE z063voMgLF^L(|X9DIOxzXGtWpZ-A;}zTIeDMGRjO;ws`+cx^7LHb0~`3T|a^ecAGkrtP zFmWP43jdSDvNIGoPNOXK_njPKVyBEj2>YrGtIXI!IfQy1FusZE(a;qA`Yp^k#DsklK8(>oEp}-^YS93TMjox%3^K_m)R;yfz z8wgZt$jP(ET~5>(bP}|%pO6f5@~!8MbSmQrd&qm zJL_rI8Ivarxt$y; zZDf?%?pIM_GD>X^t0-Blp)cn^jgG(C=vwBJaqrqPI|h%?;V3)QvQ>?NCDb0;vRlnW z75Ak&?hSov|1UF;!bGc=9=nceQ~cF`A`^++z&cjnPR9b)302p#`rWE(84hj6>saGL z!ct5nV?CSaGL9KJCqJAnuqHVnjmb3gEv5Oy1?xmKjEy)`x3%!?!3Tq#^+pp$ZW#*( z9}b#0^?e~0Y_SL?#9Wxanm9q#Zfg*`PlWGmmMrmL@PX#e`iGi1T3VV73$yG%kk|4$ z_*^-!L=R&@_)}BnPt_LbX!QzN)VS)T$1VN`nn_Ev=~-zjRL@N-7*t-7@i6C|^+eRR zpmiI(tV0i3J$h4aq#=Tqu32)jRBK}`UvAY0&+*_S_nS)=E+JufK8|;U2P)?`a%w_m znpQx2b3HHhVL^ESR8$s5m>Vn^70(b5ji}Ek z6PyK<3#gg(TrB*2Of;PlD+?k}5EUb$bwDiHFY5M-sy`Kc$5W!g+94{eiy|;0)>w~; zsxHB;*S;?re(`6Aj{zAJH9rsw9vAmnlOkk|h{eqC@q*YhB32S*y(n6& zHnD_gV{M%XnWF`)f?xc;SY&;LSbi%a8vTIRd+^#3=}qnV^XEnAyjTIP z4~Z2dy&&dM(Jum2M8x8YLRjtAN5-~#QEgol0zGRN4T}a0$4l6qq<$Jc~MmF7me1KAgJ#{v4zZd%>w?@@OxB(ns{O{J?*ToF^W@%Hp>er# z+}tBd;|`YN<{r-;&aC7T==nGIp5WmO*X~BQ2XpU161S_SY0T`XImcsFe%pM6zq9MT zx(fL&ru#qlBB%9#x7^>kcR~-BR4^v@oHjV)V}FReT~hyye6gf9Anc0T32L3>J+65v zQ0pbHpm{H7-XDY7Af@kt!X6D9pMavS``As*tHwS>@4G&BKPdX2>SGyDs>SbtQZ2rx zd4B;)c{Qb}ztPmkpteXY40ju)#R9ce@)mP1#zyO!HQ1ie7?LTbeaWGmVs@s9#F@ zkmf}-)uE+v%{!nedOuQa4{P2rP0{~5C8fT#;1^_3$*N_rTS((Ma`Siynofa8O>XS9mKT@ z%C)O`^tD9sBJ%Gnnj!t_4r2qn^q5n8%Dun0SiH1xAf1*u%@G@KWNt+k7*02R6Xj9- z?#5tX-1G)YI$-X`1Uv})OHeJaK^UXV7Ou5!`Uy%pSnkGDdl2?>P;{u=jR|SYzks3x zNBOm+9 zIO<`r1Ow~zzEZ*=GFPU@eW5JDcn_V5MYbr>A9;b0M7<4ke;GE8lHJ1v5(8ToPo=mM0G=DKsvdRY^hRPDQctsQL3t_{ewzHp)CapL88<`NJJ2|=?85JRfYOTYmtcb zy_wzhogJxvbflU2&3nIj^X6mU?ri$G27>8)Ga-993XrJ7<{gejQIrWe3i)cIXm5i` zBV&(8)4HQq@NNa;WbBpbv~Ax?S1EfMc~-SSO(NvQKqZS1uosWcSM$1o@*dsD>yJl^ zn|W)%YiknR8mQu=KOP&b?)!Tf^Y$PiMVD8{d66TrJwsK*AA*0M)mDkX9`N?|R|&E8 zeK2y(wFgTnc!T?@cmrVXUEtktd1#v3+jn;r?^X@Y8`@u``WRXPvAw>W^Y&Lycnq}v z+{7D;$L^{2?*j1dg){ItoE1#4MBrci$V9UIQF8Gg{mJt2$eW29sQP3uxik?;p5wcc zEdTl%3X|s&Ysqu<3c~WMTvSfnSmt1Ht+w><#f2ME>5U~|Exz9W*lU$`%M%^R#f1oQ z#=$5K>>2e2+`W{zk^FY@+?HqgP)mtOQd(U?7x2`2?8U?l35W+09oFw&!u92YFT3N7 z!z^;ibNTMa%g423d7_tVVFcJ1vbdnh&QNkG(VJZAcnS9~xx}Y;a}}(^I9ot8TE6T} z&F%L0BhVSNeb}L#_*58(tAMX1-%MNuF?lm_MO158ebNl{H~@6|!sj<{mJ@4>3v2T1 zwXZL%U4zw|`vWYIx2EO9)uo9wuzD5gZvmY<4JL}NiO0B!%UqmEHh%3D7<#p$570vg2`)#%d45j-b>!-^POQQh%h305`BEk6la8h1 zSC%F&gBFJbt=Anae(GW26tUz$wVdX^1qJ+^kRnAe|TmS*ZR?A}_EGqO25Rj`;Hb=;`-u)(xhgXNj_6+M?{ zre+uNSY_E6W@H_0j#+7D4r@3(riWQRl@ny`bYW)3(b9!tk>wq2wqOBm9PH)vX|Rw6 zbh=8F0#p`Vr*;W~5;v zhV3BBG*UUovmVtR!lsec=5%H;)MwcovzZCqB~_v7LjgsC2fGS~11zirUzPh&L&zgo zK*IVGWQ=oIn{c>0p#A{jAO#BmN&T@C6WYkYUTx35=s>hz>zi>(COd=+I{*#cO63lj zg;c@RwZ1I5Lpj!_km_hD?4m79iWE%cbc@tZVnYq(3uad1Mai^{tjW@vVLG6p>l!YQ zLw2rUIk0w>v;gJGfM5$8s-o2Xf{&{DLO#5r2GWJnbe<6<5Xj^UIt&>J@F87!!<12& zE@g-s?5e#B9_7ZVvAmvQxk4WHh6HznQAkKcZMuK-fdmQ0Iw=U6GZte+{*4rQ5Ly!F zgi?8?TS@;s5~V$C>$9vvvSk6;Sdc&(3Y_a)g*8RF;DF^O_O|1?$t!U=?QhLs8!n)-^72`EhUs?6 zV(D=P&sf?f`y#j<%F0jA$|ajwqh_(>kRg}<^Ruqm2Q!I0n_;G7le@W2UU{VM9oN@5 z7{Da+@JPPggp*QMetedYcFE;D0X~sHJuE-~AJh&!kKT4m9YHUG;Hw6cbbbz((VJ7p zPCQV!k`P`=$3dJ8EM(mRClfO4*0MqFcwX6J?m{d#`?(A3aiABg(6YVSbIFjM&w z#9nt;x3Zmd-k6T&)<5$AyWt0rgYPb=fo2q-J~lEkto6Fqiv`=5@3UF1&tkLvcWFmT z27J;@KcyWv%wrGtVKZ%O5N4iWDQCC);e%&lJ>e(+O-K@v=C!(zdI66aq;669r57g; zH$?`)RgZ?uN{7)IRuY8 zPq#yfSGxfB3H=I?m@mV7We=Cdq1?&QlTeBtPXQ7=zURxH_hlGicR>!2524(_(RC=d za}SH{FFWa@c|g0lb{WtYIQo{aeIC#kx$IYfFcJjFM}Y7$6(HArUM)PG z!qZMb?tFb&KcFb@u@4Z=KEOXx`Z>BEWP3O|1!#aHD0s9{faxKOJ`u@1yHJ+77M? z?I|BE`3SGf=wsOTS>ih-Jiwh72-id)y!#7;uW5nq^U=D`qrU8fkMKMTU$CDBIm}BT z!@fe61SDkeLUv_EUlz?6@L?{}=Qjz-O72td%Df8uVv@juED0=1n7*6lp+>JZb8uw{ z4=Y$-g1ni78aP80|HW_^MZ$N`Hm>uE%70>@1dgX!uPgtD!S>ynQ}HhhXQ4>iCQFt7 z!SGLnB6Y71;-bobU^r93!9QQs=^3{P9~!{HKVWs$1ZXY065KIG!oOde(|27Fj-W_* zns61W6My4^s1~v!;a@LA)#)X-iC!qu$JI)=^_E-LbI!;uIq$hrj0uW#0ZOsou9#PU ztZ2w&Y6?%8CxR12+#7`}LW#J0RC2uQiIDMLC2?U{mv|SUbqS*Xh$fWS3lm--Me-z( zO_HsfB)c|A1~*AYHc1}ZB+;uR{2uGML(rcmK_5-C=~8yeFf#=Y>(kTl8ueS2Zf2S7 zHS>naJZw9b2T?r5+x)b5pE+~JQ)S@OfRW0ZK;_lr{~7;(4mveu%oL|K-bkyjx)s;p a^*eIawYusuzTwio;a0!lC&0$v1pfs_Dl-EB literal 0 HcmV?d00001 diff --git a/makefile b/makefile index 1f15f75..8f9b23c 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,7 @@ CC = gcc FLAGS = -g -Wall -lm +# Betriebssystem erkennen und Variablen laden (hier stehen die Flags drin) ifeq ($(OS),Windows_NT) include makefile_windows.variables else @@ -12,38 +13,29 @@ else endif endif -raylibfolder = ./raylib -unityfolder = ./unity +# Objekt-Dateien, die wir für das Spiel brauchen +OBJ = stack.o bintree.o numbers.o timer.o highscore.o -# -------------------------- -# Initiales Programm bauen (zum ausprobieren) -# -------------------------- -doble_initial: - $(CC) -o doble_initial $(BINARIES)/libdoble_complete.a +# --- Hauptziel: Das Spiel bauen --- +# Hier fügen wir $(LDFLAGS) am Ende hinzu, damit -lopengl32 etc. genutzt werden +doble: main.o $(OBJ) + $(CC) $(FLAGS) main.o $(OBJ) -o doble $(LDFLAGS) -# -------------------------- -# Selbst implementiertes Programm bauen -# -------------------------- -program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o +# --- Hilfsregel: Aus .c mach .o --- +%.o: %.c + $(CC) -c $(FLAGS) $< -o $@ -doble : main.o $(program_obj_files) - $(CC) $(FLAGS) $^ -o doble +# --- Tests --- +test_stack: test_stack.c stack.o + $(CC) $(FLAGS) test_stack.c stack.o -o test_stack -$(program_obj_filesobj_files): %.o: %.c - $(CC) -c $(FLAGS) $^ -o $@ +test_numbers: test_numbers.c numbers.o bintree.o stack.o + $(CC) $(FLAGS) test_numbers.c numbers.o bintree.o stack.o -o test_numbers -# -------------------------- -# Unit Tests -# -------------------------- -unitTests: - echo "needs to be implemented" - -# -------------------------- -# Clean -# -------------------------- +# --- Aufräumen --- clean: ifeq ($(OS),Windows_NT) - del /f *.o doble + del /f *.o doble.exe test_stack.exe test_numbers.exe else - rm -f *.o doble + rm -f *.o doble test_stack test_numbers endif \ No newline at end of file diff --git a/numbers.c b/numbers.c index f59d9a2..95392f7 100644 --- a/numbers.c +++ b/numbers.c @@ -5,22 +5,81 @@ #include "numbers.h" #include "bintree.h" -//TODO: getDuplicate und createNumbers implementieren -/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. - * Sicherstellen, dass beim Befüllen keine Duplikate entstehen. - * Duplizieren eines zufälligen Eintrags im Array. - * in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ - -// Returns len random numbers between 1 and 2x len in random order which are all different, except for two entries. -// Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while -// creating random numbers. -unsigned int *createNumbers(unsigned int len) -{ - +// Vergleichsfunktion für den generischen Baum +static int compareInts(const void *a, const void *b) { + unsigned int va = *(const unsigned int*)a; + unsigned int vb = *(const unsigned int*)b; + if (va < vb) return -1; + if (va > vb) return 1; + return 0; } -// Returns only the only number in numbers which is present twice. Returns zero on errors. -unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) +unsigned int *createNumbers(unsigned int len) { + if (len < 2) return NULL; + unsigned int *array = (unsigned int *)malloc(len * sizeof(unsigned int)); + if (!array) return NULL; + + TreeNode *root = NULL; + int isDuplicate = 0; + unsigned int count = 0; + + srand(time(NULL)); + + // 1. Array mit eindeutigen Zahlen füllen + while (count < len - 1) { + // Zufallszahl generieren (Bereich groß genug wählen) + unsigned int r = (rand() % (len * 3)) + 1; + + // Versuchen in Baum einzufügen + // Wir übergeben &isDuplicate, damit Duplikate abgelehnt werden + root = addToTree(root, &r, sizeof(unsigned int), compareInts, &isDuplicate); + + if (isDuplicate == 0) { + array[count] = r; + count++; + } + } + + // Baum wird nicht mehr benötigt + clearTree(root); + + // 2. Duplikat erzeugen (einen vorhandenen Wert ans Ende kopieren) + unsigned int dupIndex = rand() % (len - 1); + array[len - 1] = array[dupIndex]; + + // 3. Mischen + for (unsigned int i = 0; i < len; i++) { + unsigned int j = rand() % len; + unsigned int temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + + return array; +} + +unsigned int getDuplicate(const unsigned int *numbers, unsigned int len) +{ + if (!numbers || len < 2) return 0; + + unsigned int *copy = (unsigned int *)malloc(len * sizeof(unsigned int)); + if (!copy) return 0; + + memcpy(copy, numbers, len * sizeof(unsigned int)); + + // Sortieren + qsort(copy, len, sizeof(unsigned int), compareInts); + + unsigned int duplicate = 0; + for (unsigned int i = 0; i < len - 1; i++) { + if (copy[i] == copy[i+1]) { + duplicate = copy[i]; + break; + } + } + + free(copy); + return duplicate; } \ No newline at end of file diff --git a/numbers.h b/numbers.h index 2315581..518c93b 100644 --- a/numbers.h +++ b/numbers.h @@ -1,12 +1,10 @@ #ifndef NUMBERS_H #define NUMBERS_H -// Returns len random numbers between 1 and 2x len in random order which are all different, except for two entries. -// Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while -// creating random numbers. +// Erzeugt ein Array mit Zufallszahlen (eine Zahl doppelt) unsigned int *createNumbers(unsigned int len); -// Returns only the only number in numbers which is present twice. Returns zero on errors. +// Findet das Duplikat unsigned int getDuplicate(const unsigned int *numbers, unsigned int len); #endif \ No newline at end of file diff --git a/numbers.o b/numbers.o new file mode 100644 index 0000000000000000000000000000000000000000..4a834a8b859ba1fe344ebb87d2c022b1e29ac0e5 GIT binary patch literal 5500 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 #include "stack.h" -//TODO: grundlegende Stackfunktionen implementieren: -/* * `push`: legt ein Element oben auf den Stack, - * `pop`: entfernt das oberste Element, - * `top`: liefert das oberste Element zurück, - * `clearStack`: gibt den gesamten Speicher frei. */ - -// Pushes data as pointer onto the stack. +// Legt ein Element auf den Stack. +// Erstellt einen neuen Knoten, setzt dessen next-Zeiger auf den aktuellen Stack +// und gibt den neuen Knoten als neuen Stack-Kopf zurück. StackNode *push(StackNode *stack, void *data) { - + StackNode *newNode = (StackNode *)malloc(sizeof(StackNode)); + if (newNode == NULL) { + // Bei Speicherfehler geben wir den alten Stack unverändert zurück + // (oder man könnte das Programm beenden) + return stack; + } + newNode->data = data; + newNode->next = stack; + return newNode; } -// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be -// freed by caller.) +// Entfernt das oberste Element. +// Gibt den Zeiger auf das nächste Element zurück (das nun oben liegt). StackNode *pop(StackNode *stack) { - + if (stack == NULL) { + return NULL; + } + StackNode *nextNodes = stack->next; + free(stack); // Nur den Knoten freigeben, nicht die Daten (data)! + return nextNodes; } -// Returns the data of the top element. +// Gibt die Daten des obersten Elements zurück. void *top(StackNode *stack) { - + if (stack == NULL) { + return NULL; + } + return stack->data; } -// Clears stack and releases all memory. +// Leert den Stack komplett. void clearStack(StackNode *stack) { - + while (stack != NULL) { + stack = pop(stack); + } } \ No newline at end of file diff --git a/stack.h b/stack.h index f7d542d..787a507 100644 --- a/stack.h +++ b/stack.h @@ -1,25 +1,27 @@ #ifndef STACK_H #define STACK_H -/* A stack is a special type of queue which uses the LIFO (last in, first out) principle. -This means that with each new element all other elements are pushed deeper into the stack. -The latest element is taken from the stack. */ - #include -//TODO: passenden Datentyp als struct anlegen +/* * Der Stack wird hier als einfach verkettete Liste implementiert. + * Der "Stack"-Pointer zeigt immer auf das oberste Element (Head). + */ -// Pushes data as pointer onto the stack. +typedef struct StackNode { + void *data; + struct StackNode *next; +} StackNode; + +// Legt ein Element auf den Stack. Gibt den neuen Kopf des Stacks zurück. StackNode *push(StackNode *stack, void *data); -// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be -// freed by caller.) +// Entfernt das oberste Element. Gibt den neuen Kopf des Stacks zurück. StackNode *pop(StackNode *stack); -// Returns the data of the top element. +// Gibt die Daten des obersten Elements zurück (ohne es zu entfernen). void *top(StackNode *stack); -// Clears stack and releases all memory. +// Leert den Stack komplett. void clearStack(StackNode *stack); -#endif +#endif \ No newline at end of file diff --git a/stack.o b/stack.o new file mode 100644 index 0000000000000000000000000000000000000000..8b0c398d32574540fcc8333c03505d387cd6581f GIT binary patch literal 3839 zcmcgvU1%It6h3!mXLpj>B$Gzc#6~mG^uN2CrfE#mzirc!joK0{!6K=3efJ1IAyAW|EbpP(8Mc!}!f; zs$707!7;o^yg7fsU1)nq$?7Byeer0?&+9|`HW}b^r+;B=6E8MU=ZG+cu}&jzpi$^s zI8Q$s+db$b9$^5VDLxg(L*5?BR1<1F2m*ZT#G|fq-oV}(3DGJhso@zZ*#T8+pCB21v*y4)LQC ziN)U&3xD+`7EkDj#fgqjse^wIBe8h=eq!OmeW(T#OUL!Qo3Ol}SeocaEb0zKk8zdb zg|GU~-15a*xS&HdL}}q}7X?Tx#Z?}Y@Zy&u2ZgNpQXlI5Lc$Nc&<1t$E~V!omR46+ zF{I=4=khYfGS1vut`nxpiuzJOW;jqj9FP>!a$Uc$Q(s@C0)^^J_|Q6|`dxfFoca#d z20pJ!018G$2%*uF6UIpY9%J|3Xn(ZNh)h?iMe|_Vvdw;MB<*zWV9`oj#iS9*!c+2S zyA1vn2|#gOVJw)=C2fozDpb0Gufs9p66-;1(z*NCXVm3X%vpISdw*=@?qy8-JBbjeiO(P6)kq(yd#?9DJ zp+OBiKxHG*r6!rMHf5V8$X_%4d88=ZDLkDl6s$DJw^=JGGGxgh8Jf}sGijfyB-7`C z?FiB|kVHfU?CKSy;yeKC=;H7)Kwt;znk!ZbSWk$;(FBroiweEIbG>@nU9XlBIkbnV z?XH3Yp2G&r!PB&FavXy6q9?74Sq4Xy1HDu&=YWNH5XaXG#;)=JA-A8ceArlMJ9SaI ztYW}fiU$oMLk?GLFKF5!O~xfADIhlw_ptriK5eW`!nG(jfvgVqNJ2A&8#~YfT8}!` zhJ&X7RlxyHA*UW)c!gToX0=UQX4+*Il)E=|x3Uc(eIrg*8vhF!`vyzHg%Y60oJ;2w;$nfMu*|f`(=9F2fPFi>(*!dZA z5|`q6T=kO~3%72$ls5~L#|WMx2s}zO4I{%b?j7UaG1oihc*knqu{v+`8n>;iot!>~ z7lPPyzL=dI9PsM7p~16*0})h3xM@#+EMH6)s<@iny#6|e`b;68isoQ+WMtUb=0qr2 z<@{WvY~~`iIn%exI9kmYDn{yc<3zqV`f`MtnX*x`t#f9&vfVjtY3OV61Va2UtTJG8 zMmVHir|CoK6_r=IoBT+#eo-1}3QD85kzM1tcJ~l)d9#A%#e4L0ae1#i!h7`Wa(Ow2 z2klNL12B(hGd=;{S-Mil91Dbf1o}+N{Ocri)E07rA4{Co=ecNHKjb}{b1n(&W>(`1-e!gsHUn0xvtk-1V2{zRh@6S@5FPPXe*pwMrK z%;?rn5&iOk)1;LpGu>}=TAw&IUB_icxBa#9jiaJBmf6T!0&0GAwDgB3vm02}=9^5; z#fl&bt})=(FVS=~zhWKDn5k;^Y`!>Uxj30h;Ti0;>|`;EcO8dV$QMl)mn*glNqv^L YZMxm`&d<-grYZb(m{50}`@d5D2Us{JCjbBd literal 0 HcmV?d00001 diff --git a/test_numbers.c b/test_numbers.c new file mode 100644 index 0000000..90e8065 --- /dev/null +++ b/test_numbers.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include "numbers.h" + +void test_create_numbers() { + printf("Teste createNumbers...\n"); + unsigned int len = 100; + unsigned int *nums = createNumbers(len); + + assert(nums != NULL); + + // Prüfen, ob genau ein Duplikat vorhanden ist + int duplicates = 0; + for (unsigned int i = 0; i < len; i++) { + for (unsigned int j = i + 1; j < len; j++) { + if (nums[i] == nums[j]) { + duplicates++; + } + } + } + // Es darf genau ein Paar geben, also duplicates == 1 + if (duplicates != 1) { + printf("FEHLER: Erwartet wurde genau 1 Duplikat, gefunden wurden %d.\n", duplicates); + } + assert(duplicates == 1); + + free(nums); + printf("createNumbers erfolgreich.\n"); +} + +void test_get_duplicate() { + printf("Teste getDuplicate...\n"); + + // Testfall 1: 3 ist doppelt + unsigned int arr[] = {1, 5, 8, 3, 9, 3, 2}; + unsigned int len = sizeof(arr) / sizeof(arr[0]); + + unsigned int dup = getDuplicate(arr, len); + if (dup != 3) { + printf("FEHLER: Erwartet 3, erhalten %u\n", dup); + } + assert(dup == 3); + + // Testfall 2: 40 ist doppelt + unsigned int arr2[] = {10, 20, 30, 40, 40}; + unsigned int len2 = sizeof(arr2) / sizeof(arr2[0]); + + dup = getDuplicate(arr2, len2); + if (dup != 40) { + printf("FEHLER: Erwartet 40, erhalten %u\n", dup); + } + assert(dup == 40); + + printf("getDuplicate erfolgreich.\n"); +} + +int main() { + test_create_numbers(); + test_get_duplicate(); + return 0; +} \ No newline at end of file diff --git a/test_stack.c b/test_stack.c new file mode 100644 index 0000000..f83574b --- /dev/null +++ b/test_stack.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include "stack.h" + +void test_stack_operations() { + printf("Teste Stack Operationen...\n"); + + // Initialisierung: Der Stack ist einfach ein Pointer auf StackNode, der mit NULL startet + StackNode *s = NULL; + + // isEmpty Test: entspricht einfach s == NULL + assert(s == NULL); + + int a = 10; + int b = 20; + + // PUSH: Gibt den neuen Kopf des Stacks zurück + s = push(s, &a); + assert(s != NULL); + assert(*(int*)top(s) == 10); // Prüfen, ob 10 oben liegt + + s = push(s, &b); + assert(*(int*)top(s) == 20); // Prüfen, ob 20 oben liegt + + // POP: Gibt den neuen Kopf zurück (das oberste Element wird entfernt) + // Achtung: pop() liefert bei dieser Implementierung NICHT die Daten zurück, + // sondern nur den neuen Stack-Pointer. Wenn man die Daten will, muss man vorher top() nutzen. + + // Prüfen vor dem Pop + assert(*(int*)top(s) == 20); + + s = pop(s); // 20 wird vom Stack genommen (Node wird freed) + + // Jetzt sollte 10 oben liegen + assert(*(int*)top(s) == 10); + + s = pop(s); // 10 wird vom Stack genommen + + // Stack sollte wieder leer sein + assert(s == NULL); + + printf("Stack Operationen erfolgreich.\n"); +} + +void test_clear_stack() { + printf("Teste Clear Stack...\n"); + StackNode *s = NULL; + int data = 42; + + for(int i = 0; i < 5; i++) { + s = push(s, &data); + } + + clearStack(s); + // Hinweis: clearStack gibt den Speicher frei, kann aber den lokalen Pointer 's' + // hier in der Funktion nicht auf NULL setzen (da C "Call by Value" nutzt). + // Wir setzen ihn manuell auf NULL oder benutzen ihn einfach nicht weiter. + s = NULL; + + printf("Clear Stack ausgeführt.\n"); +} + +int main() { + test_stack_operations(); + test_clear_stack(); + return 0; +} \ No newline at end of file diff --git a/timer.o b/timer.o new file mode 100644 index 0000000000000000000000000000000000000000..d409d89cc08d6aca0e60cbd1cd94a3057a491098 GIT binary patch literal 3066 zcmbtWOKcle6n$^T6T8@{9g>!Yf-?QkQdE!KBn@q##nh>ifK1S(Ys(V}jUio^~U6-!nK0&V#%kw7e92NL2VP{g7FL^$`onaNC}iUn7C@11+^ zx$pn0o?XvKE+-h??ajApKbT;{$w06>fs>D%uT8f#nOv{94|(;JxGZuL}W!XGeL|?jLLFn=Isp!!0oO0%t6y zGWLCFyakpyl-n~BAzpyC7>k(DE_g%vh>^5Djj>^xI0$t?@P_va-OnxpjDa`d@#HvA z-`;zD%1ujA-^jj*{~EM!P+wRCZ(nr4lOViFjfDj3R>byZ2G36{Ue!-r@jQ9qnN9z;w4A!l3ORr722G=;1qI6C>u4o^;tEfwT4FG!atuV^$0Vkx+bM%k zxqy^H5>j}rAi?h+K8y9%5J|c^{^*om930a3>@^0Byq=wN+b#1z#j?#oC}q1+KhUx& zR;#RMYwS*Sd?PjrL<9>Y+wmadysJ_#+o(O>v|2S?WbKyIsI|#aVbs_$9I`b7t9T+h+Bsi3zDX%t#6Ig*pZmt6J@u zrpe->U9Yws!7lS_}eOi20+wic~|Gt*`LgP;;U1-#$ zfFS=e=UHBa8P#kjZBXWXJN_;*U(_D(W*4tRg?L>4VOlp zjTeif`rTgKyyY}HS;wqrZS!<~w|=PIXuA5$Gx{Tq*7)ODQmc+WZ(C296?d0+erb|d zr4JCd$qHw@qo?ADw`h$Z+hq~t{^opeederE?CzTS1mqCU_xs1e=P6~6h_eOy7Ni(U zBTovnEwJqgY=?n*g!forI~ky6;00jx9I2?$N7N;{H&t<~NpB|b(qN^RcpH$CxUCu6 zEYMhhCV(iGv*XBdYQXzbrGy99ih{Bbeus?5rue*1X@H+ z3%iyh+>u`qRiW|)sG2kF z+H|8eYx%f5GlN?v(Cl)nX5zh*#Ac&q`q*)8ACh@m=wcPNpE+~Jcg^CCG+FpX4!x4A MukZiq$bYu}FUwK18UO$Q literal 0 HcmV?d00001