Avatar billede conz Juniormester
21. september 2008 - 20:20 Der er 33 kommentarer og
1 løsning

Konverter romertal fra inputfil til arabiske tal

Jeg skal bruge et program, som indlæser en række af
romertal, defineret nedenfor, fra en fil og udskriver de tilsvarende numeriske værdier (dvs.
sædvanlige arabiske tal) i sorteret rækkefølge efter deres numeriske værdi.

Inputfilen er formateret således:
V
X
VII
VI
III
V
IV
IX
II
VII

Så skulle udskriften meget gerne være sådan, så jeg får præcis ét heltal svarende til romertal i inputtet, på hver linje, sorteret efter deres numeriske værdi:
2
3
4
5
5
6
7
7
9
10

Nogen der kan hjælpe mig med dette?
Har ikke umiddelbart kunne finde noget på google, der kunne bruges tilpræcis dette formål, kun færdige convertes, der konvertere ud fra brugerinput.
Er ikke selv helt skarp til Java nemlig, men er dog i gang med at lære det.
Avatar billede arne_v Ekspert
21. september 2008 - 20:23 #1
Jeg har noget paa lageret til at konvertere fra romer tal:

public class RomanToArabic {
    private static int decodeChar(char c) {
        switch(c) {
            case 'I':
                return 1;
            case 'V':
                return 5;
            case 'X':
                return 10;
            case 'L':
                return 50;
            case 'C':
                return 100;
            case 'D':
                return 500;
            case 'M':
                return 1000;
            default:
                throw new IllegalArgumentException(c + " is not a roman digit");
        }
    }
    public static int decodeString(String s) {
        int acc = 0;
        int ix = 0;
        while(ix < s.length()) {
            if(ix < s.length() - 1 && decodeChar(s.charAt(ix)) < decodeChar(s.charAt(ix + 1))) {
                acc -= decodeChar(s.charAt(ix));
            } else {
                acc += decodeChar(s.charAt(ix));
            }
            ix++;
        }
        return acc;
    }
    public static void main(String[] args) {
        System.out.println(decodeString("III"));
        System.out.println(decodeString("IV"));
        System.out.println(decodeString("V"));
        System.out.println(decodeString("VI"));
        System.out.println(decodeString("MCMXCIX"));
        System.out.println(decodeString("MMVII"));
    }
}
Avatar billede arne_v Ekspert
21. september 2008 - 20:25 #2
Saa skal du:
- laese input filen en linie ad gangen
- konvertere fra romertal til normal tal med decodeString ovenfor
- gemme i en ArrayList<Integer>
- sortere denne
- udskrive den til en ny fil
Avatar billede conz Juniormester
21. september 2008 - 20:38 #3
Der ser da fint ud det der.
Må indrømme jeg nogenlunde forstår koden når jeg læser den, kan godt se logikken i det osv., men rammer lidt muren med dit anden indlæg.

Hvordan skal jeg fortælle programmet (din kode) at det fx er "romertal.txt" filen den skal læse fra, og hvordan kun en linie af gangen? (og kan denne fil egentlig bare gemmes som .txt eller skal dette også være java?)
Kan ikke gennemskue med hvad det er jeg skal konvertere? Altså er det "ix" jeg skal kalde?

Sortering? Det skal jeg nok finde ud af, det kan en googlesøgning vel godt svare mig på.

Når jeg udskriver til en ny fil, så er det noget i retning af

out = new FileOutputStream("minfil.txt");

, right? Og kan denne også godt nøjes med at være .txt ?
Avatar billede arne_v Ekspert
21. september 2008 - 20:46 #4
BufferedReader br = new BufferedReader(new FileReader(filename));
String line;
while((line = br.readLine()) != null) {
  ...
}

er en god maade at laese paa.
Avatar billede arne_v Ekspert
21. september 2008 - 20:47 #5
PrintWriter pw = new PrintWriter(new FileWriter(newfilename));
for(int i = 0; i < lst.size(); i++) {
    pw.println(lst.get(i));
}
pw.close();

vil skrive ud.
Avatar billede arne_v Ekspert
21. september 2008 - 20:47 #6
der mangler lige en

br.close();

til sidst i laesningen.
Avatar billede conz Juniormester
21. september 2008 - 20:51 #7
Så RomanToArabic koden så stå i inden i BufferedReader koden?
på "..." 's plads?

Og PrintWriter skal bare være nederest i programmet? Eller?

Sorry, men er som sagt i SÅ meget inde i Java.
Avatar billede arne_v Ekspert
21. september 2008 - 20:51 #8
Ja. Med en add til en ArrayList<Integer>.

Ja.
Avatar billede conz Juniormester
21. september 2008 - 20:56 #9
Jeg skal ikke importe Scanner her, eller sådan noget sjov?
Så i det hele hvordan skal det se ud?
Og hvor skal jeg så egentlig køre main fra?

Noget i retningen af?

BufferedReader br = new BufferedReader(new FileReader(filename));
String line;
while((line = br.readLine()) != null) {
  ...
}
Avatar billede conz Juniormester
21. september 2008 - 20:58 #10
Hov, kom til at trykke send.


BufferedReader br = new BufferedReader(new FileReader(filename));
String line;
while((line = br.readLine()) != null) {

public class RomanToArabic {
    private static int decodeChar(char c) {
        switch(c) {
            case 'I':
                return 1;
            case 'V':
                return 5;
            case 'X':
                return 10;
            case 'L':
                return 50;
            case 'C':
                return 100;
            case 'D':
                return 500;
            case 'M':
                return 1000;
            default:
                throw new IllegalArgumentException(c + " is not a roman digit");
        }
    }
    public static int decodeString(String s) {
        int acc = 0;
        int ix = 0;
        while(ix < s.length()) {
            if(ix < s.length() - 1 && decodeChar(s.charAt(ix)) < decodeChar(s.charAt(ix + 1))) {
                acc -= decodeChar(s.charAt(ix));
            } else {
                acc += decodeChar(s.charAt(ix));
            }
            ix++;
        }
        return acc;
    }
    public static void main(String[] args) {
        System.out.println(decodeString("III"));
        System.out.println(decodeString("IV"));
        System.out.println(decodeString("V"));
        System.out.println(decodeString("VI"));
        System.out.println(decodeString("MCMXCIX"));
        System.out.println(decodeString("MMVII"));
    }
}
}
br.close();

også skal jeg vel have
public static void main(String[] args)
her?

Hvad mener du med add til en ArrayList? Det skal bare stå til sidst i RomanToArabic klassen eller hvad?
Avatar billede conz Juniormester
21. september 2008 - 21:01 #11
int KonvTal;
KonvTal = new int[10]

noget i den stil?
Avatar billede arne_v Ekspert
21. september 2008 - 21:21 #12
Kun en klasse nemlig din.

3 metider: decodeChar, decodeString, main

du skal kun kalde decodeString i while loekken ikke have koden der
Avatar billede conz Juniormester
21. september 2008 - 21:32 #13
Okay, må indrømme jeg er faldet lidt af hesten.

Gider du ikke prøve at opsummere lidt, for kan ikke rigtig følge med. Heh, sorry.
Avatar billede arne_v Ekspert
21. september 2008 - 21:40 #14
en klasse - din

3 metoder

decodeChar - fra min klasse
decodeString - fra min klasse
main - lav ArrayList<Integer>
      laes ind fra fil med while loekke (se kode skitsering)
      sorter
      udskriv til fil med for loekke (se kode skitsering)
Avatar billede conz Juniormester
21. september 2008 - 21:47 #15
Jamen hvordan får jeg så de konverterede tal i min array?
Altså, hvordan skal det se ud til i det hele?

i min main der skal jeg have
ArrayList<Integer>
og hvordan fortæller jeg den at jeg skal gemme de tal der bliver konverteret? Eller er det først efter while løkken?
Avatar billede arne_v Ekspert
21. september 2008 - 21:54 #16
lst.add(decodeString(line));

skulle tilfoeje et tal til listen.
Avatar billede conz Juniormester
21. september 2008 - 22:07 #17
Så ?

public class RomanToArabic {
    private static int decodeChar(char c) {
        switch(c) {
            case 'I':
                return 1;
            case 'V':
                return 5;
            case 'X':
                return 10;
            case 'L':
                return 50;
            case 'C':
                return 100;
            case 'D':
                return 500;
            case 'M':
                return 1000;
            default:
                throw new IllegalArgumentException(c + " is not a roman digit");
        }
    }
    public static int decodeString(String s) {
        int acc = 0;
        int ix = 0;
        while(ix < s.length()) {
            if(ix < s.length() - 1 && decodeChar(s.charAt(ix)) < decodeChar(s.charAt(ix + 1))) {
                acc -= decodeChar(s.charAt(ix));
            } else {
                acc += decodeChar(s.charAt(ix));
            }
            ix++;
        }
        return acc;
    }
    public static void main(String[] args) {
        System.out.println(decodeString("III"));
        System.out.println(decodeString("IV"));
        System.out.println(decodeString("V"));
        System.out.println(decodeString("VI"));
        System.out.println(decodeString("MCMXCIX"));
        System.out.println(decodeString("MMVII"));
    }
}

public static void main(String[] args){

BufferedReader br = new BufferedReader(new FileReader(RomerTal.txt));
String line;
while((line = br.readLine()) != null) {

    public static int decodeString(String s)

}
br.close()
}


Er det rigtigt indtil videre?
Og hvad skal jeg så?
Forstår stadig ikke hvordan jeg skal implementere det med ArrayList, og hvordan jeg så skal få denne sorteret.
Avatar billede arne_v Ekspert
21. september 2008 - 22:38 #18
ArrayList<Integer> lst = new ArrayList<Integer>();

laver en ArrayList.

lst.add(decodeString(line));

tilfoejer til den
Avatar billede conz Juniormester
21. september 2008 - 22:52 #19
Så jeg skal erstatte alle dine System.out.println(decodeString())
med BufferRead, også inde i den lst.add(decodeString(1)) ?

Hvor jeg før det selvf. har lavet lst = new ArrayList<Interger>();
Avatar billede arne_v Ekspert
21. september 2008 - 22:56 #20
du skal slet ikke bruge noget fra min main - den er kun til test
Avatar billede conz Juniormester
21. september 2008 - 22:58 #21
Det giver selvfølgelig en masse fejl. Øv.

En masse "cannot find symbol" ved lst.add og BufferRead og hvad der ellers har med det at gøre.
Avatar billede conz Juniormester
21. september 2008 - 23:01 #22
public class RomanToArabic {
    private static int decodeChar(char c) {
        switch(c) {
            case 'I':
                return 1;
            case 'V':
                return 5;
            case 'X':
                return 10;
            case 'L':
                return 50;
            case 'C':
                return 100;
            case 'D':
                return 500;
            case 'M':
                return 1000;
            default:
                throw new IllegalArgumentException(c + " is not a roman digit");
        }
    }
    public static int decodeString(String s) {
        int acc = 0;
        int ix = 0;
        while(ix < s.length()) {
            if(ix < s.length() - 1 && decodeChar(s.charAt(ix)) <

decodeChar(s.charAt(ix + 1))) {
                acc -= decodeChar(s.charAt(ix));
            } else {
                acc += decodeChar(s.charAt(ix));
            }
            ix++;
        }
        return acc;
    }
    public static void main(String[] args) {

    lst = new ArrayList<Integer>();

        BufferedReader br = new BufferedReader(new FileReader(RomNum.txt));
        String line;
        while((line = br.readLine()) != null) {
        lst.add(decodeString(1));
        lst.add(decodeString(2));
        lst.add(decodeString(3));
        lst.add(decodeString(4));
        lst.add(decodeString(5));
        lst.add(decodeString(6));
        lst.add(decodeString(7));
        lst.add(decodeString(7));
        lst.add(decodeString(8));
        lst.add(decodeString(10));

        }

    }
}


Det er det jeg har prøvet med nu, hvor RomNum.txt ser således ud:
V
X
VII
VI
III
V
IV
IX
II
VII

også får jeg alle de overstående fejl. 7 af dem.
Avatar billede arne_v Ekspert
21. september 2008 - 23:05 #23
Du skal nok lige importe java.io.* og java.util.* - og saa mangler du ar erklaere lst - og
saa skal du decode line ikke nogle tal.
Avatar billede conz Juniormester
21. september 2008 - 23:32 #24
Hm, det er nok java.util.Scanner jeg skal importere, hvad skulle java.io.* være?

Erklære lst? Hvad betyder/hvordan det?

så jeg skal lst.add(decodeStrin(line)); og kun EN gang så, eller?
Avatar billede conz Juniormester
21. september 2008 - 23:35 #25
Har java.util.Scanner i starten af koden, og får nu en fejl når jeg prøver at compile:

"error: Class names, RomanToArabic, are only acceptet if annotation processing is explicity requested"

?
Avatar billede conz Juniormester
21. september 2008 - 23:51 #26
Do'h, ja selvfølgelig.

Nå, får stadig de fejl omkring BufferReader, også forsætter den ned til lst.add.

Hvordan er det jeg skal erklære lst, hvad betyder det?
Avatar billede conz Juniormester
21. september 2008 - 23:54 #27
Er det ikke det jeg har gjort med lst = new ArrayList ?
Avatar billede arne_v Ekspert
22. september 2008 - 08:20 #28
21/09-2008 22:38:26
Avatar billede knudmuhko Nybegynder
28. oktober 2008 - 10:32 #29
Man kan også løse problemet med recursion. men her er et lille program der efter hvad jeg forstår skulle kunne løse problemet:

import java.io.*;
import java.util.*;

public class RomanToNumbers {

    public static void main(String[] args) throws IOException {
        String inputFile = "c:/in.txt";
        String outputFile = "c:/out.txt";
        FileReader read = new FileReader(inputFile);
        BufferedReader buf = new BufferedReader(read);
        List<Integer> lst = new ArrayList<Integer>();
        String input = buf.readLine();
        do {
            lst.add(decodeString(input));
            input = buf.readLine();
        } while (input != null);
        buf.close();
        read.close();
        FileWriter fw = new FileWriter(outputFile);
        BufferedWriter writer = new BufferedWriter(fw);
        for (Integer number : lst) {
            writer.write(number);
        }
        writer.close();
        fw.close();
    }

    public static int decodeString(String input) {
        if (input == null) {
            throw new NullPointerException("Input cannot be null!");
        }
        if (input.length() == 0) {
            return 0;
        }
        if (input.length() == 1) {
            return decodeChar(input.charAt(0));
        }
        int firstChar = decodeChar(input.charAt(0));
        int secondChar = decodeChar(input.charAt(1));
        int result = 0;
        if (secondChar > firstChar) {
            result = -firstChar;
        } else {
            result = firstChar;
        }
        return result + decodeString(input.substring(1));
    }

    private static int decodeChar(char c) {
        switch (c) {
            case 'I':
                return 1;
            case 'V':
                return 5;
            case 'X':
                return 10;
            case 'L':
                return 50;
            case 'C':
                return 100;
            case 'D':
                return 500;
            case 'M':
                return 1000;
            default:
                throw new IllegalArgumentException(c + " is not a roman digit");
        }
    }
}
Avatar billede knudmuhko Nybegynder
28. oktober 2008 - 10:36 #30
Glemte at sortere, men kan gøres ved at indsætte:

Collections.sort(lst);

i linje 21 altså lige før:

FileWriter fw = new FileWriter(outputFile);
Avatar billede knudmuhko Nybegynder
28. oktober 2008 - 10:39 #31
og for loopet skal ændres til:

for (Integer number : lst) {
    writer.append(number + "\n");
}
Avatar billede conz Juniormester
17. august 2010 - 12:22 #32
løst
Avatar billede arne_v Ekspert
17. august 2010 - 15:12 #33
Uden hjaelp??
Avatar billede conz Juniormester
17. august 2010 - 15:35 #34
Nej arne_v undskyld, det var med meget hjælp, primært din, der gjorde at jeg kom igennem det.
Det var faktisk bare for at lukke tråden jeg besvarede, troede du havde glemt alt o denne tråd.
Jeg oprette lige et ekstra spørgsmål, hvor jeg tildeler dig pointene.
http://www.eksperten.dk/spm/916563
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester