Roman Numerals in Java 8

TDD · asj · Created at · Last by hkliya Replied at · 1240 hits
377

前一段在公司里组织Dojo,练的题目是罗马数字。顺便自己平时也练了几遍。

问题

把一个正整数转换成罗马数字。转换规则如下

基本符号

符号 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

符号按照数值大小排列,数值相加即为整个数字的值,如
VI = V+ I = 5 + 1 = 6

  • 如果 I 出现在 V 或 X 前,表示5或10减1
  • 如果 X 出现在 L 或 C 前,表示50或100减10
  • 如果 C 出现在 D 或 M 前,表示500或1000减100

如 CD = C + D = -100 + 500 = 400

注意: 不能把999写作100-1 -> IC

测试

import org.junit.*;
import static org.junit.Assert.*;

public class RomanTest {

    @Test
    public void testSingleSignal() {
        assertEquals("I", new Roman(1).toString());
        assertEquals("V", new Roman(5).toString());
        assertEquals("X", new Roman(10).toString());
        assertEquals("L", new Roman(50).toString());
        assertEquals("C", new Roman(100).toString());
        assertEquals("D", new Roman(500).toString());
        assertEquals("M", new Roman(1000).toString());
    }

    @Test
    public void test_4s_and_9s() {
        assertEquals("IV", new Roman(4).toString());
        assertEquals("IX", new Roman(9).toString());
        assertEquals("XL", new Roman(40).toString());
        assertEquals("XC", new Roman(90).toString());
        assertEquals("CD", new Roman(400).toString());
        assertEquals("CM", new Roman(900).toString());

    }

    @Test
    public void II_2() {
        assertEquals("II", new Roman(2).toString());
    }

    @Test
    public void test_complex_number() {
        assertEquals("MCMXLVII", new Roman(1947).toString());
    }
}

代码

import java.util.stream.Stream;

public class Roman {
    static class DefinedNumerical extends Roman {
        String signal;
        DefinedNumerical(int digit, String signal) {
            super(digit);
            this.signal = signal;
        }
        @Override
        public String toString() {
            return signal;
        }
    }


    static final Roman[] definedRomans = new Roman[] {
        new DefinedNumerical(1000, "M"),
        new DefinedNumerical(900, "CM"),
        new DefinedNumerical(500, "D"),
        new DefinedNumerical(400, "CD"),
        new DefinedNumerical(100, "C"),
        new DefinedNumerical(90, "XC"),
        new DefinedNumerical(50, "L"),
        new DefinedNumerical(40, "XL"),
        new DefinedNumerical(10, "X"),
        new DefinedNumerical(9, "IX"),
        new DefinedNumerical(5, "V"),
        new DefinedNumerical(4, "IV"),
        new DefinedNumerical(1, "I")
    };

    int digit;

    public Roman(int digit) {
        this.digit = digit;
    }

    private boolean hasPart(Roman defined) {
        return digit >= defined.digit;
    }

    private String combinePart(Roman matched) {
        return matched.toString() + new Roman(digit - matched.digit);
    }

    @Override
    public String toString() {
        return Stream.of(definedRomans)
            .filter(this::hasPart)
            .findFirst()
            .map(this::combinePart)
            .orElse("");
    }
}

过程见 http://cyber-dojo.org/dashboard/show/CA84C40E95
过程小错误较多,见笑了


「软件匠艺社区」旨在传播匠艺精神,通过分享好的「工作方式」和「习惯」以帮助程序员更加快乐高效地编程。
共收到 1 条回复
1
hkliya · #1 ·

需要 Sign In 后回复方可回复, 如果你还没有账号你可以 Sign Up 一个帐号。