Diskuze: Machr na algoritmy - římská čísla
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Tvůrce

Zobrazeno 49 zpráv z 49.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.
#include "stdafx.h"
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
unordered_map<string, int> n = {
{ "I", 1 },
{ "IV", 4 },
{ "V", 5 },
{ "IX", 9 },
{ "X", 10 },
{ "L", 50 },
{ "C", 100 },
{ "D", 500 },
{ "M", 1000 },
};
int number;
while (cin >> number)
{
for (auto i = n.rbegin(); i != n.rend(); ++i)
{
while (number - i->second >= 0)
{
number -= i->second;
cout << i->first;
}
}
cout << endl;
}
return 0;
}
Pro inspiraci
To je až moc jednoduché, práce tak na 10 minut, to už víc času zabere to komentování. Nechceš změnit zadání?
Musí být číslo jakékoli, nebo může být omezené jen na max 9999 - pak už jsou to samé MMMMM ...
Unafený Konyk, mohol by si niečo skúsiť, nech sa toľko neflákaš
Třeba já to dělám trochu složitější a některé funkce nahrazuji vlastním kódem
A zadání udělá složitější a pak si hromada lidí bude stěžovat, že je to složité. Żádné takové, nech zadaní zadáním. Přidej k tomu třeba zpětnou konverzi.
pokud Vám to přijde jednoduché není nic jednoduší, než, že si to vy sami něčím vylepšíte.
Kompaktní řešení.
public class MagicSquare{enum
N{M(0x3e8),CM(01604),D(0x1f4)
,CD(0620),C(0144),XC(0132),L(
062),XL(050),X(0b1010),IX(011
),V(5),IV(0b100),I(0b1);final
int v; N(int va){this.v=va;}}
public static String toRoman(
int i){String r=""; for(N n:N
.values()){while(n.v <=i){i-=
n.v;r+=n.name();}}return r;}}
assert MagicSquare.toRoman(-1).equals("");
assert MagicSquare.toRoman(0).equals("");
assert MagicSquare.toRoman(11).equals("XI");
assert MagicSquare.toRoman(93).equals("XCIII");
Ahoj, tady je odkaz na moje řešení napsané v Pythonu.
Ještě dotaz - proč je to vlákno umístěné v sekci pro Javu?
Moje řešení http://leteckaposta.cz/800884961
Řešení v Prologu (GNU Prolog), základem je predikát conversion/2 se
vstupně/výstupními parametry.
Dál už je kód samopopisný
% knowledge base for romans characters
romans('M', 1000). romans('CM', 900). romans('D', 500). romans('CD', 400).
romans('C', 100). romans('XC', 90). romans('L', 50). romans('XL', 40).
romans('X', 10). romans('IX', 9). romans('V', 5). romans('IV', 4). romans('I', 1).
% numeral/2, numeral(?Roman, +Arabic)
numeral('', 0).
numeral(Roman, Arabic) :- romans(Rh, Ah), Ah =< Arabic, !,
Am is Arabic - Ah, numeral(Rt, Am), atom_concat(Rh, Rt, Roman).
% numeral/3, numeral(?Roman, -Arabic, +Acc)
numeral('', 0, 0).
numeral(Roman, Arabic, Arabic) :- numeral(Roman, Arabic), !.
numeral(Roman, Arabic, Acc) :- An is Acc - 1, numeral(Roman, Arabic, An).
% conversion/2, conversion(?Roman. ?Arabic)
conversion('', 0).
conversion(Roman, Arabic) :- integer(Arabic), !, numeral(R, Arabic), R = Roman.
conversion(Roman, Arabic) :- numeral(Roman, Arabic, 4999).
Test cases:
:- initialization(main).
main :- conversion(R, 19), write(R), nl, fail.
main :- conversion('XIX', A), write(A), nl, fail.
main :- conversion(R, 99), write(R), nl, fail.
main :- conversion('XCIX', A), write(A), nl, fail.
main :- conversion(R, 1957), write(R), nl, fail.
main :- conversion('MCMLVII', A), write(A), nl, fail.
main :- conversion('XIX', 19), write(ok), nl, fail.
main :- conversion('XCIX', 99), write(ok), nl, fail.
main :- conversion('MCMLVII', 1957), write(ok), nl, fail.
main.
Michale, posílám upravenou verzi, která je jednodušší a efektivnější. Přece jenom jsem dlouho v PL nedělal, takže chvilku trvá, než se přizpůsobí myšlenkové pochody.
% romans/2, romans((?Roman, ?Arabic)
romans("M", 1000). romans("CM", 900). romans("D", 500). romans("CD", 400).
romans("C", 100). romans("XC", 90). romans("L", 50). romans("XL", 40).
romans("X", 10). romans("IX", 9). romans("V", 5). romans("IV", 4). romans("I", 1).
% numeral/2, numeral(?Roman, +Arabic), numeral(+Roman, ?Arabic)
numeral([], 0).
numeral(Roman, Arabic) :- integer(Arabic), !, romans(Rh, Ah), Arabic >= Ah, !,
At is Arabic - Ah, numeral(Rt, At), append(Rh, Rt, Roman).
numeral(Roman, Arabic) :- romans(Rh, Ah), append(Rh, Rt, Roman), !,
numeral(Rt, At), Arabic is Ah + At, !, numeral(Roman, Arabic).
% conversion/2, conversion(?Roman, +Arabic), conversion(+Roman, ?Arabic)
conversion(Roman, Arabic) :- integer(Arabic), !, numeral(Rc, Arabic), atom_codes(Roman, Rc).
conversion(Roman, Arabic) :- atom(Roman), atom_codes(Roman, Rc), !, numeral(Rc, Arabic).
Test cases:
:- initialization(main).
main :- conversion(R, 14), write(R), nl, fail.
main :- conversion('XIV', A), write(A), nl, fail.
main :- conversion(R, 99), write(R), nl, fail.
main :- conversion('XCIX', A), write(A), nl, fail.
main :- conversion(R, 1957), write(R), nl, fail.
main :- conversion('MCMLVII', A), write(A), nl, fail.
main :- conversion(R, 8765), write(R), nl, fail.
main :- conversion('MMMMMMMMDCCLXV', A), write(A), nl, fail.
main :- conversion('XIV', 14), write(ok), nl, fail.
main :- conversion('XCIX', 99), write(ok), nl, fail.
main :- conversion('MCMLVII', 1957), write(ok), nl, fail.
main :- conversion('IL', _), write(fail), nl, fail.
main :- conversion('IXI', _), write(fail), nl, fail.
main.
Zde zasílám řešení http://leteckaposta.cz/801187890 Pokud to nebude fachšit na
windows, tak napiš a já se to pokusim napravit . V zipu je i video z iPhone
simulatoru.
Pár tipů pro iOS:
No, v AppStoru bys zaručeně dostal rejection, čeká tě ještě hodně práce.
Tak přidávám též svoje řešení. Napsal jsem ho v PHP a umí pouze
převádět z arabských čísel na římská čísla. Snad se bude líbit.
On-line: http://application.wz.cz/machr/
Ke stažení: http://leteckaposta.cz/356433278
Omlouvám se, ale až teď odpoledne jsem si uvědomil, že existuje i více
římských čísel, než jsem měl v původním programu. Proto dávám na
nový program nový odkaz. Snad to nebude vadit.
Ke stažení: http://leteckaposta.cz/853804761
Moje řešení:
http://leteckaposta.cz/319444479
Moje řešení:
http://leteckaposta.cz/177410904
Mé řešení:
https://drive.google.com/…Qjljdmc/view?…
Jelikož mi nejde stránka letecká pošta a nevím proč, tak tady vložím
přímo kód. Snad vám to nebude moc vadit
|
public class PrevodNaArabske {
public static void main(String[] args) {
String rimske = "MCCXXXIV";
int aktualni = 0, minulaCislice = 0, arabske = 0;
//číslice(znaky) čte od konce (zprava) a zjišťuje zda byla předchozí číslice menší nebo větší a podle toho počítá
for(int i = rimske.length()-1; i >= 0; i--){
//inicializace aktuálního čísla
switch(rimske.charAt(i)) {
case 'I': aktualni = 1; break;
case 'V': aktualni = 5; break;
case 'X': aktualni = 10; break;
case 'L': aktualni = 50; break;
case 'C': aktualni = 100; break;
case 'D': aktualni = 500; break;
case 'M': aktualni = 1000; break;
}
//pokud je minulaCislice větší než aktuální, tak se od arabskeho odečte aktuální, a pokud je menší nebo rovna, tak se přičte
if(minulaCislice > aktualni) {
arabske -= aktualni;
} else {
arabske += aktualni;
}
//inicializace minuleCislice
minulaCislice = aktualni;
}
//výpis arabského čísla
System.out.println(arabske);
}
}
Taky jsem se rozhodl pro svoje řešení. [Python]
protože jsem zapoměl zmínit čas deadline, tak do dnešní půlnoci máte ještě spoustu času. Jak říkal Lukáš Křehula, je to "práce tak na 10 minut".
Tento algoritmus se mi líbí, ale neřeší ostatní převody z římských čísel. Kdyby String rimske bylo např. "IIV" tak by výsledek byl 5, jelikož čteme od konce to znamená 5-1+1 (číslo před není větší(není žádne=0)+5(V),číslo před je větší(I=1<V=5)-1,číslo před není větší (I=1je rovno I=1) takže +1 a to se rovná 5...
Tak tedy ještě vysvětlení mého kódu...
V Javě bohužel nemůžeme moc elegantně inicializovat mapy nebo 2D pole s
více typy a itaraci dvou polí jsem se chtěl vyhnout (ošklivý for i cyklus),
proto jsem jako formát dat jsem zvolil enum. Kromě základních římských
číslic jsem deklaroval i čísla složená, typu: IV, IX,... řešení těchto
speciálních případů by jen zesložitilo kód.
Konstanty jsou úmyslně seřazeny sestupně podle své hodnoty.
private enum Numbers {
M(1000), CM(900), D(500), CD(400),
C(100), XC(90), L(50), XL(40),
X(10), IX(9), V(5), IV(4),
I(1);
private final int value;
private Numbers(int value) {
this.value = value;
}
public int value() {
return value;
}
}
A dále už je to jasné...
public static String toRoman(int integer) {
String result = "";
for (Numbers number : Numbers.values()) {
while (number.value() <= integer) {
integer -= number.value();
result += number.name();
}
}
return result;
}
Toto je jen pro porozumění hodnoťte kód postnutý výše
Jo sorry za ten koment předtím. Já si neuvědomil že nejde IIV
. Byl jsem do toho tak zažrán
že jsem si to neuvědomil.
Ano:) a právě proto tohle nemusím řešit v mém algoritmu, protože 3 je
římsky III, nikoli IIV
Jo právě a to jsem si neuvědomil takže jsem to složitě řešil v mém
algoritmu
Toto řešení mě také napadlo s tím switchem ale já jsem si to
neuvědomil a řešil jsem to tak jak jsem psal předtím...
Ještě jsem na tvé řešení nedíval na žádné řešení ještě
pak kouknu na ta řešení, která
vyhrála
To jste tu skoro všichni museli definovat 4 a 9 ?
Ne, já ne. Já definoval jen ty základní, viz nahoře
Tentokrát dorazilo nevídaně mnoho řešení. Většina z Vás si vybrala Javu nebo C#. Někteří z Vás to využili jako ukázku něčeho zajímavého. Ačkoliv algoritmus může být jednoduchý, moc se mi nezamlouvalo, když do programu pošlete předvyplněné pole a on to jenom nějak slepí. Tak jako jste k těm hodnotám pole došli vy, mohl k tomu dojít program. Protože řešení je strašně moc, tak mi docela dělalo problém zpětně zjišťovat, kdo se jmenuje Number, převody římských čísel a podobně.
Tukmak
Tvoje řešení je oboustranné, objektové, umí validovat, bohužel na úkor
přehlednosti a jednoduchosti, šlo to pole, kde máš všechny jednotky,
desítky a stovky. Nesedí mi tam ta metoda, pro vypisování „O programu“,
třída by měla dělat jednu věc, ne 2 (počítat a vypisovat) čímž ses
vlastně i částečně zbavil rozšiřitelnosti kódu, protože z tohoto
vypisování lze vycítit, že třída byla navržena jen pro tebe jen do tohoto
machra a nikam dál s ní nepočítáš.
Kokosmán
Tvůj kód je jednoduchý a účelný, všechno je v main. Switch by se moc
neměl používat, šlo to vyřešit polem. Do budoucna je lepší to dělat
objektově nebo minimálně do funkcí/metod.
Fuull - (10 bodová penalizace)
Nijak v tom názvu Number nevidím tvůj nick (-10 bodů). Název Parser není
moc výstižný pro římská čísla. Algoritmus je jednoduchý, nemá
zbytečné pole, které nepotřebuje a je skoro zázračně krátký.
Omega
Název Prevadec, je hodně obecný Mělo by tam být zmíněno to hlavní –
Římská čísla. Kód je napatlaný v jedné třídě a děláš toho
zbytečně moc v Mainu. Existuje taková poučka, že řádek kódu by neměl
mít více jak 80 znaků. Nemusíš se toho striktně držet, ale je fajn, když
se mi to vleze i do okna a editor to nemusí znásilňovat nějakým
rozždákováním nebo dalším scrollbarem. V Charu máš „dvoj chary“,
takže to není až zas tak výstižné a hlavně to je zbytečné. Jak jsi
došel k tomu, že CM = 900? Nemohl k tomu dojít program sám?
Hartrik
Tvůj kód je sice skladný a celkem krátký, ale v reálu to asi
nepoužijeme.
Škrášek Michal – (10 bodová penalizace)
V názvu převod římských čísel.zip nikde nevidím tvůj nick (-10
bodů) Tvůj kód je napsaný v Mainu výchozí třídy. Na první pohled není
vůbec jasné, co dělá, chtělo by to nějak pojmenovat.
1001001
PřevodČísel není vhodný název. Za prvné nevíme jakých čísel a za
druhé v názvech by neměla být diakritika. Kolekce obsahuje věci, ke kterým
mohl program dojít sám. Kód je naplácaný v Mainu.
Werty
Název Vypocet s metodou Preved? Trochu divné, když se třída jmenuje podle
toho, co nedělá. Kód je však celkem pěkný a překvapivě krátký.
Kaczmi
Kontrola1, Kontrola2, … by šlo vyřešit lépe, minimálně podle názvu, ale
tak zrovna u kontrol to není taková tragédie. příště se podívej na
rozhraní (IKontrola, metoda Kontroluj) a třídy KontrolaNeco : IKontrola.
Gcx11 – (10 bodová penalizace)
Neumíš pojmenovat soubor podle svého jména (-10 bodů). Tvůj kód vypadá
dobře, jen k tomu šílenému poli mohl program dojít sám.
dave23
Tvůj kód není vůbec špatný, akorát si taky pohlídej délku řádku.
Taková doporučená délka je 80 znaků. Visual Studio ti to píše na stavové
liště.
coells
Hezká ukázka již ne příliš známého jazyka.
Phyber
Na Windows je hustě rozbombardované kódování složek a názvu souborů. A
spousta editorů neumí odřádkování i přesto jsem se tím nějak letmo
prokousal, škoda že jsi to takhle nedal na poprvé a spoustu chyb si opravil
až po upozornění coelsem.
IT Man
Není to vůbec objektové. Spousta věcí se tam několikrát neskutečně
opakuje, to co lze jednoduše vyřešit polem, děláš asi 10 funkcemi. Zkus si
pohlídat délku řádku, abys na menším monitoru v editoru horizontální
scroolbar.
Tomisoka
Kód je spíše nepřehledný, ale poměrně krátký. Komentáři ses moc
nezabýval a jde to poznat.
Frofo1 – (10 bodová penalizace)
Neumíš pojmenovat soubor podle svého jména (-10 bodů). Tak tento kód je
fakt úžasný, krátky, přehledný, bez zbytečností a bez potřeby
složitého komentáře u každého řádku.
Tomáš Bitter
Kód je pěkný a komentář „NEPOUŽÍVAT, NEFUNGUJE PŘEVOD DEVÍTEK (A
NAVÍC JE V TOM BORDEL)“ mě docela pobavil. Jestli jsi ten druhý směr
nestihl, tak si to měl smazat. Ze C#pistů jsi to měl asi nejlepší, tady by
se taky dala udělit placka.
Jsem rád, že jste to zkusili, příště nezapomeňte, že i malé aplikace
a algoritmy programujeme objektově, protože když Vás to chytí, tak se to
bude rozšiřovat a pak se v tom začnete ztrácet. Kód by měl být dobře
čitelný pro každého. Krátký kód = (ale výjimky se najdou) lepší kód,
jelikož je toho ke zkoumání méně. Osobně jsem uděloval i body, ale ty
nemají vypovídající hodnotu (snad krom penalizací), protože většina z
Vás na tom byla víceméně stejně. Za porušení pravidel jsem tentokrát
body jenom odečítal, příště budu diskvalifikovat. V 17 řešeních se fakt
špatně dohledává, kdo odevzdává soubor Number.zip a podobné. Zdrojové
kódy jsem zkoumal v Poznámkovém bloku a některé specifičtější v
PSpadu. Je třeba si však uvědomit, že pokud ty řádky (hlavně s
komentáři) budou hodně dlouhé, tak buď tam editor přidá scroolbar nebo to
rozděli na více řádků a tím se to akorát znepřehledňuje. 80 znaků sice
nemusíte striktně držet, ale jestli to překročíte 3×, tak se někde stala
chyba. Nezapomeňte, že většina jazyků má víceřádkové komentáře a ze
srandy králíkům tam nejsou. Zkuste program nechat řešit vše, když mu
něco předvypočítáne je to sice super a možná rychlejší, ale zbytečně
se to akorát komplikuje. Úplně stačilo jedno pole s těmi základními
číslicemi. Placky teda rozdám 2. Úplný vítěz je Frofo1, který
neumí pojmenovat soubor (příště by byl diskvalifikován) a ještě se mi
celkem líbilo řešení od Tomáš Bitter. Prosím publikovat a o placku pak
požádejte Zdeněk Pavlátka.
kéž by jenom 4 a 9. Někteří definovali skoro všechno.
Ono je to ale celkem logické, protože podle CrashTestova řešení se jakékoliv menší číslo, které je před větším odečítá od toho většího. Tím pádem pokud zadáš "IM" tak je výsledek 999. To je ale špatně, mělo by to hodit výjimku.
IV = 4
IX = 9
XL = 40
XC = 90
CD = 400
CM = 900
To znamená, že číslo 999 v římských číslicích je CMXCIX
CM = 900
XC = 90
IX = 9
900+90+9 = 999
Na to já jsem myslel, proto tam mám tolik kontrol a jelikož pracovat s rozhraními ještě neumím, tak jsem to udělal tak jak jsem to udělal.
Každopádně gratuluji vítězům.
Kaczmi.
není to špatně, protože to pravidlo není povinné, alespoň podle wikipedie.
Povinné není ani programovat objektově nebo psát komentáře, je to jen lepší a rozšířenější.
Není to povinné tak proč to brát jako chybu? Pokud uživatel bude používat toto pravidlo tak mu to nic nezmění, pokud nebude používat toto pravidlo tak se jedině tak naštve, že to nefunguje...
Toto pravidlo není povinné a pokud to není uvedeno v zadání jako
podmínka tak bych to tak nehrotil..
Skončeme to takhle:
Za všechno mohou Římané. Měli si vytvořit neprůstřelnější číselnou soustavu (jako máme teď my).
Jdeme na pivo ...
Zobrazeno 49 zpráv z 49.