Transaction
48DD07F2AA95A5…9E0CBD6A7C36
Block 25,950 · index 0 · indexed
Summary
- Hash
- 48DD07F2AA95A5CB643430F0EA3A93A2540E2C11559B560001A89E0CBD6A7C36
- Block
- 25,950
- Size
- 4118 bytes
- Gas used
- 8,675,635 / 10,410,822
- Fee
- 1000000ugnot
- Memo
- gnopublish
- Status
- success
Messages
Arguments · 9
- #1romannum
- #2README.md
- #3# `gno.land/p/moul/x/daily/romannum/v0` **Roman-numeral converter** — `ToRoman`, `FromRoman`. A pure port of the classic kata, valid for **1..3999**. `ToRoman` uses greedy subtractive notation (panics out of range); `FromRoman` accepts a numeral only if it is canonical (it must round-trip through `ToRoman`), so malformed forms like `IIII`, `VV`, or `IC` are rejected. Deterministic — no time, randomness, or I/O — and free of any realm coupling. ```go import "gno.land/p/moul/x/daily/romannum/v0" s := romannum.ToRoman(2024) // "MMXXIV" n := romannum.FromRoman(s) // 2024 (panics on a malformed numeral) ``` **Live demo:** [`r/moul/x/daily/romannumdemo`](https://github.com/moul/gno-contracts/tree/main/r/moul/x/daily/romannumdemo/v0) · render it at [`/r/moul/x/daily/romannumdemo/v0`](https://gno.land/r/moul/x/daily/romannumdemo/v0). <!-- BEGIN GNOCONTRACTS FOOTER (generated by `make readmes`; do not edit below) --> --- Part of **[moul/gno-contracts](https://github.com/moul/gno-contracts)** — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage. > 🧪 **Highly experimental — potentially vibe-coded.** Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: [DISCLAIMER](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md). <!-- END GNOCONTRACTS FOOTER -->
- #4gnomod.toml
- #5module = "gno.land/p/moul/x/daily/romannum/v0" gno = "0.9"
- #6romannum.gno
- #7// Package romannum is a pure port of the classic Roman-numeral converter kata: // ToRoman / FromRoman, valid for 1..3999. Deterministic — no time, randomness // or I/O — and free of any realm coupling, so it is reusable as a library. // // A live demo of this package (an interactive integer↔Roman converter) is at // [r/moul/x/daily/romannumdemo](/r/moul/x/daily/romannumdemo/v0). package romannum import ( "strconv" "strings" ) // romanUnits is the greedy subtractive-notation table, largest value first. var romanUnits = []struct { val int sym string }{ {1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"}, {90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"}, } // ToRoman renders an integer in 1..3999 as a Roman numeral. // It panics if n is out of range. func ToRoman(n int) string { if n < 1 || n > 3999 { panic("romannum: out of range (want 1..3999): " + strconv.Itoa(n)) } var b strings.Builder for _, u := range romanUnits { for n >= u.val { b.WriteString(u.sym) n -= u.val } } return b.String() } // FromRoman parses a Roman numeral back to an integer. // It panics on any malformed input (e.g. "IIII", "IC", "VV"). func FromRoman(s string) int { n, ok := parseRoman(s) if !ok { panic("romannum: invalid roman numeral: " + s) } return n } // charVal maps a single Roman digit to its value, or 0 if unknown. func charVal(c byte) int { 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 } return 0 } // parseRoman is the pure, panic-free core used by FromRoman. // It returns (value, true) only for a canonical numeral: it accepts input // iff ToRoman(value) reproduces it exactly, which rejects malformed forms. func parseRoman(s string) (int, bool) { s = strings.ToUpper(strings.TrimSpace(s)) if s == "" { return 0, false } total, prev := 0, 0 for i := len(s) - 1; i >= 0; i-- { v := charVal(s[i]) if v == 0 { return 0, false } if v < prev { total -= v } else { total += v prev = v } } if total < 1 || total > 3999 || ToRoman(total) != s { return 0, false } return total, true }
- #8/gno.MemPackageType
- #9 MPUserProd
Result log
msg:0,success:true,log:,events:[]