Pārlūkot izejas kodu

AK: Add generation of roman numerals to AK::String

We now can generate roman numbers using String::roman_number_from()
similar to String::bijective_base_from().
Tobias Christiansen 4 gadi atpakaļ
vecāks
revīzija
87033ce7d1
2 mainītis faili ar 54 papildinājumiem un 0 dzēšanām
  1. 53 0
      AK/String.cpp
  2. 1 0
      AK/String.h

+ 53 - 0
AK/String.cpp

@@ -273,6 +273,59 @@ String String::bijective_base_from(size_t value, unsigned base, StringView map)
     return String { ReadonlyBytes(buffer.data(), i) };
 }
 
+String String::roman_number_from(size_t value)
+{
+    if (value > 3999)
+        return String::number(value);
+
+    StringBuilder builder;
+
+    while (value > 0) {
+        if (value >= 1000) {
+            builder.append('M');
+            value -= 1000;
+        } else if (value >= 900) {
+            builder.append("CM"sv);
+            value -= 900;
+        } else if (value >= 500) {
+            builder.append('D');
+            value -= 500;
+        } else if (value >= 400) {
+            builder.append("CD"sv);
+            value -= 400;
+        } else if (value >= 100) {
+            builder.append('C');
+            value -= 100;
+        } else if (value >= 90) {
+            builder.append("XC"sv);
+            value -= 90;
+        } else if (value >= 50) {
+            builder.append('L');
+            value -= 50;
+        } else if (value >= 40) {
+            builder.append("XL"sv);
+            value -= 40;
+        } else if (value >= 10) {
+            builder.append('X');
+            value -= 10;
+        } else if (value == 9) {
+            builder.append("IX"sv);
+            value -= 9;
+        } else if (value >= 5 && value <= 8) {
+            builder.append('V');
+            value -= 5;
+        } else if (value == 4) {
+            builder.append("IV"sv);
+            value -= 4;
+        } else if (value <= 3) {
+            builder.append('I');
+            value -= 1;
+        }
+    }
+
+    return builder.to_string();
+}
+
 bool String::matches(const StringView& mask, Vector<MaskSpan>& mask_spans, CaseSensitivity case_sensitivity) const
 {
     return StringUtils::matches(*this, mask, case_sensitivity, &mask_spans);

+ 1 - 0
AK/String.h

@@ -99,6 +99,7 @@ public:
     [[nodiscard]] static String repeated(const StringView&, size_t count);
 
     [[nodiscard]] static String bijective_base_from(size_t value, unsigned base = 26, StringView map = {});
+    [[nodiscard]] static String roman_number_from(size_t value);
 
     template<class SeparatorType, class CollectionType>
     [[nodiscard]] static String join(const SeparatorType& separator, const CollectionType& collection)