Python and Viv · Strings
Palindromes
What to notice
"".join(c.lower() for c in s if c.isalnum())and"yes" if is_palindrome(p) else "no"are the same in both.c.isalnum()andc.lower()are Python's, Unicode included, so"Été"becomesétéon both sides.t[::-1]reverses a string in both. (It does not reverse a Viv array of numbers: a slice step there must be 1 or more.)return Falseisreturn false: Viv's booleans are lower case.i, j = 0, len(t) - 1is the same statement in both.
Python palindrome.py · 37 lines
Viv palindrome.viv · 47 lines
py2viv translated from palindrome.py
What py2viv adds before the program
(nothing)
(nothing)
15 lines: a header and the guard functions its translation calls
1###
2Translated from palindrome.py by py2viv 0.2.0 (numeric Python -> Viv).
3Python source sha256: f2823adbf00b4ad2446fbe127485e40eb395fad7933215d2c8eae37daa53d2a9
4Each print(...) is one print(...) line; fmt(x) writes a float as Python's repr does.
5A `raise`, a failed assert and every guard `stop` with Python's exception line.
6###
7
8#| An int result, as Python's int: a -0.0 becomes 0 (an int has no sign on zero), and the run
9#| stops at 2^53, past which a double no longer holds every integer (Python's int does).
10def py_int(x) {
11 if abs(x) >= 9007199254740992 {
12 stop("py2viv: an integer reached 2^53; Python's int is exact there and a double is not")
13 }
14 return x + 0.0
15}
1 keep letters and digits, in lower case
4def normalize(s):
5 return "".join(c.lower() for c in s if c.isalnum())
2def normalize(s) {
3 return "".join(c.lower() for c in s if c.isalnum())
4}
20def normalize(s) {
21 return join("", [lower(py_c3) for py_c3 in s if isalnum(py_c3)])
22}
2 compare with the reverse
8def is_palindrome(s):
9 t = normalize(s)
10 return t == t[::-1]
7def is_palindrome(s) {
8 t = normalize(s)
9 return t == t[::-1]
10}
24def is_palindrome(s) {
25 t = normalize(s)
26 return t == t[::-1]
27}
3 compare from both ends
13def is_palindrome_two_ends(s):
14 t = normalize(s)
15 i, j = 0, len(t) - 1
16 while i < j:
17 if t[i] != t[j]:
18 return False
19 i += 1
20 j -= 1
21 return True
13def is_palindrome_two_ends(s) {
14 t = normalize(s)
15 i, j = 0, len(t) - 1
16 while i < j {
17 if t[i] != t[j] {
18 return false
19 }
20 i += 1
21 j -= 1
22 }
23 return true
24}
29def is_palindrome_two_ends(s) {
30 t = normalize(s)
31 i = 0
32 j = len(t) - 1
33 while i < j {
34 if t[i] != t[j] {
35 return false
36 }
37 i = py_int(i + 1)
38 j = py_int(j - 1)
39 }
40 return true
41}
4 try some phrases
24PHRASES = [
25 "A man, a plan, a canal: Panama",
26 "Was it a car or a cat I saw?",
27 "No lemon, no melon",
28 "Hello, world",
29 "Été",
30]
31for p in PHRASES:
32 verdict = "yes" if is_palindrome(p) else "no"
33 print(f"{verdict:3} {normalize(p)}")
27PHRASES = [
28 "A man, a plan, a canal: Panama",
29 "Was it a car or a cat I saw?",
30 "No lemon, no melon",
31 "Hello, world",
32 "Été"
33]
34for p in PHRASES {
35 verdict = "yes" if is_palindrome(p) else "no"
36 print(f"{verdict:3} {normalize(p)}")
37}
43PHRASES = ["A man, a plan, a canal: Panama", "Was it a car or a cat I saw?", "No lemon, no melon", "Hello, world", "Été"]
44for py_i4 to len(PHRASES) {
45 p = PHRASES[py_i4]
46 verdict = ("yes" if is_palindrome(p) else "no")
47 print(fmt(verdict, "3"), normalize(p))
48}
5 checks
36for p in PHRASES:
37 assert is_palindrome(p) == is_palindrome_two_ends(p)
40test "two ways agree" {
41 for p in PHRASES {
42 assert_true(is_palindrome(p) == is_palindrome_two_ends(p))
43 }
44}
50for py_i5 to len(PHRASES) {
51 p = PHRASES[py_i5]
52 if not (is_palindrome(p) == is_palindrome_two_ends(p)) {
53 stop("AssertionError")
54 }
55}
What they print
identical — the two programs print the same text.
Dimmed lines are left out of the comparison. Each Viv test block prints one PASS line; the Python checks the same facts with assert, which prints nothing.
$ python3 palindrome.py
yes amanaplanacanalpanamayes wasitacaroracatisawyes nolemonnomelonno helloworldyes été
$ viv run palindrome.viv
yes amanaplanacanalpanamayes wasitacaroracatisawyes nolemonnomelonno helloworldyes étéPASS two ways agree
$ viv run palindrome.py (py2viv’s translation)
The translation prints exactly what the Python prints.
yes amanaplanacanalpanamayes wasitacaroracatisawyes nolemonnomelonno helloworldyes été