From bf02648bb3660f48c74acdd2bb8bd7b4a9dd3781 Mon Sep 17 00:00:00 2001 From: trochas Date: Fri, 12 Dec 2025 16:43:56 +0100 Subject: [PATCH] Exo 1 en cours --- .../java/fr/istic/vv/RomanNumeraUtils.java | 155 +++++++++++++++++- .../java/fr/istic/vv/RomanNumeralTest.java | 112 +++++++++++++ .../fr/istic/vv/RomanNumeraUtils.class | Bin 661 -> 4053 bytes .../fr/istic/vv/RomanNumeralTest.class | Bin 645 -> 4361 bytes 4 files changed, 261 insertions(+), 6 deletions(-) diff --git a/code/roman-numerals/src/main/java/fr/istic/vv/RomanNumeraUtils.java b/code/roman-numerals/src/main/java/fr/istic/vv/RomanNumeraUtils.java index a37e18a..857046c 100644 --- a/code/roman-numerals/src/main/java/fr/istic/vv/RomanNumeraUtils.java +++ b/code/roman-numerals/src/main/java/fr/istic/vv/RomanNumeraUtils.java @@ -1,11 +1,154 @@ package fr.istic.vv; +import java.util.HashMap; +import java.util.Map; + public class RomanNumeraUtils { + + final static Map mapToNum = new HashMap<>(); + static { + mapToNum.put('M', 1000); + mapToNum.put('D', 500); + mapToNum.put('C', 100); + mapToNum.put('L', 50); + mapToNum.put('X', 10); + mapToNum.put('V', 5); + mapToNum.put('I', 1); + } + + public static boolean isValidRomanNumeral(String value) { + boolean isValid = true; + + char lastChar = ' '; + int nbLastChar = 0; + int valMax = 1001; + + for(int i = 0; imapToNum.get(lastChar)){ + //seul I X C peuvent soustraire un symbole (ex : IX XC CM) + if(lastChar == 'I' || lastChar == 'X' || lastChar == 'C'){ + valMax = mapToNum.get(lastChar)-1; + //si plus de 1 soustraction (ex IIX) ou que la soustraction est ni 1/10 ni 1/5 du chiffre le plus grand + if(nbLastChar>1 || !(mapToNum.get(val)/10==mapToNum.get(lastChar) || mapToNum.get(val)/5==mapToNum.get(lastChar))){ + isValid = false; + } + } + else isValid = false; + } + + } + switch (val){ + case 'M': + case 'C': + case 'X': + case 'I': + if(lastChar==value.charAt(i)){ + nbLastChar++; + if(nbLastChar>3) isValid = false; + } + else{ + lastChar = value.charAt(i); + nbLastChar = 1; + } + break; + case 'D': + case 'L': + case 'V': + if(lastChar==value.charAt(i)){ + nbLastChar++; + if(nbLastChar>1) isValid = false; + } + else{ + lastChar = value.charAt(i); + nbLastChar = 1; + } + break; + default: + isValid = false; + } + } + else isValid = false; + } + + return isValid; + } + + public static int parseRomanNumeral(String numeral) { + if(isValidRomanNumeral(numeral)){ + + int res = 0; + char lastChar = ' '; + + for(int i = 0; ivalue){ //XIX + res += 0; + } // - + else if(lastChar!=' ' && value>mapToNum.get(lastChar)){ //IX + res += value-mapToNum.get(lastChar); + } + else{ + res +=mapToNum.get(val); + } + lastChar = val; + } + return res; + } + else throw new IllegalArgumentException("Invalid date"); + + } + + public static String toRomanNumeral(int number) { + System.out.println(number); + String res = ""; + char[] order = {'M','D','C','L','X','V','I'}; + char[] sub = {'I','X','C'}; + if(number<4000){ + while(number>0){ + boolean notFound = true; + for(int i = 0; i=val){ + number -= val; + res = res + symb; + System.out.println(res); + notFound = false; + } + else{ + boolean notFoundSub = true; + for(int j = 0; j=val-valSub){ + number -= val-valSub; + res = res + symbSub + symb; + System.out.println(res); + notFoundSub = false; + notFound = false; + } + } + + } + } + + } + } + System.out.println("Return : " + res); + return res; + } + else throw new IllegalArgumentException("max 4000"); - public static boolean isValidRomanNumeral(String value) { return false; } - - public static int parseRomanNumeral(String numeral) { return 0; } - - public static String toRomanNumeral(int number) { return ""; } - + } + } diff --git a/code/roman-numerals/src/test/java/fr/istic/vv/RomanNumeralTest.java b/code/roman-numerals/src/test/java/fr/istic/vv/RomanNumeralTest.java index ded8e7a..c3b9972 100644 --- a/code/roman-numerals/src/test/java/fr/istic/vv/RomanNumeralTest.java +++ b/code/roman-numerals/src/test/java/fr/istic/vv/RomanNumeralTest.java @@ -1,8 +1,120 @@ package fr.istic.vv; import net.jqwik.api.*; import net.jqwik.api.constraints.IntRange; +import static fr.istic.vv.RomanNumeraUtils.*; public class RomanNumeralTest { + + + + @Example + void simpleValidRomanNumerals() { + assert isValidRomanNumeral("I"); + assert isValidRomanNumeral("II"); + assert isValidRomanNumeral("III"); + assert isValidRomanNumeral("IV"); + assert isValidRomanNumeral("VI"); + assert isValidRomanNumeral("VIII"); + assert isValidRomanNumeral("IX"); + assert isValidRomanNumeral("X"); + assert isValidRomanNumeral("XI"); + assert isValidRomanNumeral("MI"); + assert isValidRomanNumeral("XIII"); + } + + @Example + void nonValidRomanNumeralsBadLetter() { + assert !isValidRomanNumeral("IIIA"); + assert !isValidRomanNumeral("A"); + assert !isValidRomanNumeral("CAI"); + } + + @Example + void nonValidRomanNumeralsRepeated() { + assert !isValidRomanNumeral("IIII"); + assert !isValidRomanNumeral("XXXX"); + assert !isValidRomanNumeral("CCCC"); + assert !isValidRomanNumeral("MMMM"); + assert !isValidRomanNumeral("DD"); + assert !isValidRomanNumeral("LL"); + assert !isValidRomanNumeral("VV"); + } + + @Example + void validRomanNumeralsLeftSub() { + assert isValidRomanNumeral("IV"); + assert isValidRomanNumeral("IX"); + assert isValidRomanNumeral("XL"); + assert isValidRomanNumeral("XC"); + assert isValidRomanNumeral("CD"); + assert isValidRomanNumeral("CM"); + + } + + @Example + void nonValidRomanNumeralsLeftSub() { + assert !isValidRomanNumeral("VX"); + assert !isValidRomanNumeral("VL"); + assert !isValidRomanNumeral("IL"); + assert !isValidRomanNumeral("IC"); + assert !isValidRomanNumeral("VC"); + assert !isValidRomanNumeral("LC"); + assert !isValidRomanNumeral("ID"); + assert !isValidRomanNumeral("VD"); + assert !isValidRomanNumeral("XD"); + assert !isValidRomanNumeral("LD"); + assert !isValidRomanNumeral("IM"); + assert !isValidRomanNumeral("VM"); + assert !isValidRomanNumeral("XM"); + assert !isValidRomanNumeral("LM"); + assert !isValidRomanNumeral("DM"); + } + + @Example + void completValidRomanNumerals() { + assert isValidRomanNumeral("MCDXXXIV"); + assert isValidRomanNumeral("DCCLXXXIX"); + assert isValidRomanNumeral("LXIX"); + assert isValidRomanNumeral("MCCXXXIV"); + + } + + @Example + void completNonValidRomanNumerals() { + assert !isValidRomanNumeral("IXX"); + assert !isValidRomanNumeral("IXIXIX"); + assert !isValidRomanNumeral("MMMDCCCLIXXXVIII"); + assert !isValidRomanNumeral("XIXV"); + + } + + + @Example + void testParseRomanNumeral() { + assert parseRomanNumeral("XX")==20; + assert parseRomanNumeral("XIX")==19; + assert parseRomanNumeral("XXI")==21; + assert parseRomanNumeral("IX")==9; + assert parseRomanNumeral("MCCXXXIV")==1234; + } + + + + + @Example + void testToRomanNumeral() { + assert toRomanNumeral(20).compareTo("XX")==0; + assert toRomanNumeral(19).compareTo("XIX")==0; + assert toRomanNumeral(21).compareTo("XXI")==0; + assert toRomanNumeral(9).compareTo("IX")==0; + assert toRomanNumeral(1234).compareTo("MCCXXXIV")==0; + assert toRomanNumeral(3999).compareTo("MMMCMXCIX")==0; + } + + + + + @Property boolean absoluteValueOfAllNumbersIsPositive(@ForAll @IntRange(min=Integer.MIN_VALUE +1) int anInteger) { return Math.abs(anInteger) >= 0; diff --git a/code/roman-numerals/target/classes/fr/istic/vv/RomanNumeraUtils.class b/code/roman-numerals/target/classes/fr/istic/vv/RomanNumeraUtils.class index 9cae7b4e405632aa14d7e2f4abc3db7b830188b6..72c1d5f897bc6826cf984d764756141b2f0ab7fd 100644 GIT binary patch literal 4053 zcma)8U2qfE75=WY(&`T^8)U#Xt`mM@42~%Q6R>dt0^15UfBwNX0lbzr_F{S0kyb8F zLK3JG0!af+ND5?9e(H`p6K2|^8UE6yoj&xT(}%wFsnhr5sWY8)TG9mfyDQn2z?13N zyV`s1x#ynqo$s7`|8)QE=Kwb2Cn{V570;#WjI?dU>&C|F4p<|axhFHCr?f8HNTyXN z0^wuYm{yn6%)z?71IP5ZE#Mo`MmsGk3KX?D(;2GQwQHjd0{#wT(A4ZqN*CBtINO*V zI<}%iT1t!Cda5B$7&C2skfJ8q@ioSihH2PM0`BTH-2zI~O6V#U2o%rl*{Y?7xNiU< z6on8*K)~DREb~L4Bm@t<0W3zTiip6XxmafR4`B(G3aDdRGNbQ(PGD(ubWNU5vx*G? zl%YaJ`HTZj966VzmE{7Z)v^4wGw}rRJv^eKN?^g9>vTJWN3nwOjb@1Ilht{0Nf}djP{U`7N~6duFMnvMMkL zJ~xH%l$`P=b#u@j67V=IknqhhB^M@H*ho|*G+Pf~AG&0Xu$JacBju{;R6l)nr*yJpp=~|rUID>#*!b}* zj;J_XnE&y#t&fCo6#X=3Ns33Zuo_m~J~GGVYF!&)T@4_iB0f`}h0`JEU{$K4az)b2 zGN{`JW(y_kWXD1n1|429q7Ca&%ZzLGLBk&6SK8K0n?XF5&y}3V1tp%7Nk2@vU3UrL zW^oSVd4cNrR?oM*1TLiIq6g`jGoN3%Igt-zPB%SXwQ>D=StW#@HB25_sf7G>9U`^d z>C6DtOv`SzGG>AZq{l}n3C>756LAkHJlmE?`%0R@=C5?Vdwa$K9BmLJpFkZK+Z%|OC~!ETW=`x;x!-M zBBVn2@HSBu^5Z<=IiT~jGOM;$38!LAJr!kbr*)ox?+UDXDEj&0QSlyo>UXO$zuDmN z2>InEcX`;z1B$;YM=tm{^1%;T?m*#h;)!+x@SvXN3YLlW31)?4)3KWRCDe@IaVw5Pel8+s4SMt4@-hw^{_*Y4v zH}D|dg$3xrLK30~C)jV!p%|;26*6L;(YfgA_{$=Or{)$`&zY2PfS|}Fp{xQPLp4W! z*#IdaG_Ko(hM^ z@OzZq#FmJ1U9?t&tFGYFd1fi9aMsW2PvWhLaO?_-D#ATi;I9Zruj2T_YD%JBS+4vH zJ@Xh12a*pjxPp!IsQTvB47eMo;BhxbydM#h(|ja(qI|aV*~urtCzczx<;Lx~ad&Rq zBgYk4sIDSB;TFrilW3B*w`8T;l%^@v7OE(dD3>awc`7shOn5}ZQ*#sBu0t)qeE+5L z8{EPT$&$CRg73v-cqtjagbpudYRlNaEBLO&4xaC=sKO}kL#L>Fk;(rjx%Cy({%Jng{dqI?HIWa}006U1HgRTUS|j26Za66fe&3lv_U&Jx-d zMo}g#JVQM%b~Cm$SUAmayeihQudtEe8(8AMuoS*_lm<(K%GVICuNk%{iOTZ%nKa{Fu3N6K$}hJC#y2X3MBcZ?#N>}Hlb zaDec3GS)6ee2|h}ro0ceyeM?yFeOJgI*K2lpY1`zJBZ^KJb6Fj%uNj9HVh|8O<8m( zmE88@muxI8#4dyzxg;&*I++kR?Z4|JMBy$kGp#a7GBpu+@1vMG`Ibx&n=nY_s~gxE~#KEWZj1+8STEv){=)9Vhmcl9daon5`2aI~w}8*c0BRl_}9y}odF zS8v!Gj&-$r9le;;)v}0s4V8Q+8rDX< zcNsa_=*QZd7;)DtQ%EWGK6kx;3WsYW{*CnknHRR}0!joULElhBy@CaiU^u|9t5`>i zkznE)R%Ab<^?!`*6BZx^ovPFgGJ> zf92#nQ;_r5d87d*b8fM{kMd^!JWD41w9$bK;U04`ZetuT@b4A8h&S*O^M8W* ze;M!LRTln9{FE(V5EnLJu#55DK_h){;khLF)`Z}F>|-NPagzVv!Y8TM zAYaZ`tq}K6?V6^#SInx(mf^aGU@^TqMJp~MFu~u&9G|84Z#wTEIq!4$v5bt;cW{AG GFZ&;H*{C1@ literal 661 zcma)(%TB^j5QhKh#R4K%@rowyz^Gliz_>9nA!#%bW#R5nDjrf=(-xk}g|19o_y9hX zaax;LAyGFoXU@zwGv`0=AFpo!jd!3U6dy4#tih5tdG*C!+G_U++L=Fe3Q&OUTyX$YjqQq3^#S_sjU2khfIMSYBIhSW2p qf(oh$SwsC#()dBHrep(aDS4RARBP)`b3^kPRK+H?I8WG4s+yn49DpVO diff --git a/code/roman-numerals/target/test-classes/fr/istic/vv/RomanNumeralTest.class b/code/roman-numerals/target/test-classes/fr/istic/vv/RomanNumeralTest.class index 6884cff00099989ab4c844440267e457d25c54af..6e32f2fce7179851f8c9753a4110ef9787aed6aa 100644 GIT binary patch literal 4361 zcma)9X>%J@7Cldrt+u1YvK+}<;(;s>vqTWW8UwN0Sw!T-*p86H+Lk*>J94+^Zkr@5 z12cqmn80L!AsNUF5SS%1Y%`F8D)Z}bO0^NDr^s{sK-e(=k8Wk(M?XV%uY|$`4rgH7L0Bhp7 z@W%_V*SE@~XD!x|Z_8`)FOc4lud_MnyOw=m%iz8^E@IGi#d%7%xvt~3V?DYx3<^YY zISrSR;hem%-i-TDf(?teA#x&T80J+evpjq&t2za9d30N5d{& zjq#&lj6sc#YS=@W&uh4qvcM+nU2Lje-rVm`F3f0{;+i7Ya#^HEYeh<(HrUJ&od#Da zV>`e7PA)4joV%r@8G|xMS(1|G*rAaEa zm}g*cx2lR7j>%4uygx3`n&Wq$-r5>M-Tp2}jaW1f~Z$`wgy+UF1%H(bvQpBxRp zmq``n8F)5<=kN!f@5<6uKhodqfj=^os{0q@MUjn=l76O~uoG$gr36mml)wtVK_xBc z2Aj`LJ6^`=I9_QOd9`zuz+YsPZIUCyHK!a6ukx0;>tjVd$DUbh%y>?D!Iy(#!Q8Wd zxLmG{DKF=ZJD%lRi)@7$9ka1|mJEk+*Qs!v9^qkH(>PN|o-uFo_%sZc%#!`v9hd&N zd)*R6iL=Oe4a@euY|i#4IK)jZi_Tki^kG1><1GFi$G^x?ePWCm{=o#^!rNTPtZGq{ z{V{alBeGkcZ2u6|OZ)T~$jNi6#a z>!&}!#h(P|1|@ol61_}`Zd9UIDA7$ybh8q@Mu}dhL~m$B>!fdDon);tSdPp1{2oCE zib%pnCmtoSBnEG@6rZsIUvt&}&|NK1jpAsh1_qr-m2w~AS;W)=gXDD_a3Er>EoF4mRNeG^1?Du`~h(PMyaSE4(W z=q*Y#uS9n%(eXyKp7k200IXrwYnk;rX1$)ZyNI>Bm^5!-?FK_EoC>kfhImjb8kkTr z@m0XYu^?x4Z>#%tk`Xtbq`gY?HYGaUh}Lr+;7kE7XU-d$bCx+@!JMyT&YPI?=1{)J zLiuWFt>w$Tx2w_>pV!hAyMlD@U;xc+d6yEsM~TiT(OD(BUx^-6qH{{LtVC@kT2Z2| z67`knq7psah}MfX!hr%@$D&=&qTRrvZDG-dShO2iw42zdH*?5r<&YWXkQw2S(S?Rl zF~FC_&Dbt(!H#-i#ja3cJJAsuI&%8Z(NR@}aXM(|>7c^*Guq}ReNc)1T8Tc=h}QGX z@VN!-V!nCiJI0K5GvD!g4ww$*(2AJMfjfTtivoX?Zkt>4F(vwh5`C%>T^jfl1K-QQ z3k>`=20s0>f&We!_@@EmN2`pdQ_q~k@#MYPdDQnI>(c3OYuyK z^*G)c`!b}cXVzDJC%KEX-_40}4|c-f?+lKh6w2;ss4Q``^mKQ3_pmN6D%1OaklvYU zdOgXN=kTZ0Gwy5_o>!{cq-v8w)ypiU?h&P~#&@{tGE-X?xa0=B!-u%2z6C}h+VC#7 Qt$@gcJqWzV+X(*iJziF_4FCWD delta 318 zcmYL@KTiTd6vXH4-QK|+AfO_6Cni?-k1I`#v9Zw@Dvi{u5Jd@ETx@N$uq0dh6=l^szkfcz0PJDihZ4lLBJp^q-tZ0vqd|Hoa9W!e0{7^? z*AL(zKc2R2PFl9BckQXf_E~qE0hY1iqb4Zbnn#li&FDJmnDnNAIvRG{i>h)WD4wO} z>aJrR&duepZ+l+*2~ZGdcvPQvBy^$cttoQv1ciW_Jp(R6YGEFr7r6l?Eby)}DN9x8 yRgRzaEM~wtCM$XvePHPg+MPHPt`7G9%l%n-ZJzrp53!1fzvEe4^29ZwLh~1^A0_et