Palindrome detection: Difference between revisions

(Added Z80 Assembly version)
(22 intermediate revisions by 17 users not shown)
Line 218:
(equal (rest xs) ys)
(equal xs ys)))))</syntaxhighlight>
 
=={{header|Acornsoft Lisp}}==
 
This is a small Lisp that doesn't have strings; symbols are used instead. <code>Explode</code> takes a symbol and returns a list of single-character symbols, one for each character in the symbol's name. <code>Implode</code> does the reverse.
 
Since the exact palindrome tests compares two symbols, it can use <code>eq</code>, and <code>equal</code> isn't needed.
 
The character set is ASCII. Given a symbol, <code>ordinal</code> returns the numeric ASCII code of the the first character in the symbol's name. <code>Character</code> goes in the other direction and returns a single-character symbol.
 
The peculiar definition of <code>digit-p</code> is because it's not possible to type a symbol that has a digit character as its name, and so the ''between'' comparison has to be defined using the character before '0' and the one after '9'.
 
<syntaxhighlight lang="lisp">
(defun palindrome-type (text)
(cond ((exact-palindrom-p text) 'exact)
((inexact-palindrome-p text) 'inexact)
(t 'not-a-palindrome)))
 
(defun exact-palindrom-p (text)
(eq text (implode (reverse (explode text)))))
 
(defun inexact-palindrome-p (text)
(exact-palindrom-p (implode (normalise (explode text)))))
 
(defun reverse (list (result . ()))
(map '(lambda (e) (setq result (cons e result)))
list)
result)
 
(defun normalise (chars)
(cond ((null chars)
nil)
((not (alphanumeric-p (car chars)))
(normalise (cdr chars)))
((upper-case-p (car chars))
(cons (to-lower-case (car chars))
(normalise (cdr chars))))
(t
(cons (car chars) (normalise (cdr chars))))))
 
(defun between-p (lowest-value n highest-value)
(not (or (lessp n lowest-value)
(greaterp n highest-value))))
 
(defun alphanumeric-p (ch)
(or (lower-case-p ch) (upper-case-p ch) (digit-p ch)))
 
(defun digit-p (ch)
(between-p (add1 (ordinal '/))
(ordinal ch)
(sub1 (ordinal ':))))
 
(defun upper-case-p (ch)
(between-p (ordinal 'A) (ordinal ch) (ordinal 'Z)))
 
(defun lower-case-p (ch)
(between-p (ordinal 'a) (ordinal ch) (ordinal 'z)))
 
(defun to-lower-case (ch)
(character (plus (ordinal ch)
(difference (ordinal 'a) (ordinal 'A)))))
 
(defun examples ()
(map '(lambda (text)
(printc '!" text '!"
'! is! (palindrome-type text)))
'(a
abba Abba
abcba
baba
Able! was! I! ere! I! saw! Elba!!
In! girum! imus! nocte,! et! consumimur! igni)))
</syntaxhighlight>
 
{{Out}}
 
Calling <code>(examples)</code> will output:
 
<pre>
"a" is exact
"abba" is exact
"Abba" is inexact
"abcba" is exact
"baba" is not-a-palindrome
"Able was I ere I saw Elba!" is inexact
"In girum imus nocte, et consumimur igni" is inexact
</pre>
 
=={{header|Action!}}==
Line 1,116 ⟶ 1,202:
palindrome
</pre>
 
=={{header|Bruijn}}==
<syntaxhighlight lang="bruijn">
:import std/String .
 
main [<~>0 =? 0]
 
:test (main "tacocat") ([[1]])
:test (main "bruijn") ([[0]])
</syntaxhighlight>
 
=={{header|Burlesque}}==
Line 1,779 ⟶ 1,875:
return true
}</syntaxhighlight>
 
=={{header|EasyLang}}==
<syntaxhighlight lang="easylang">
func$ reverse s$ .
a$[] = strchars s$
for i = 1 to len a$[] div 2
swap a$[i] a$[len a$[] - i + 1]
.
return strjoin a$[]
.
func palin s$ .
if s$ = reverse s$
return 1
.
return 0
.
for s$ in [ "rotor" "rosetta" "step on no pets" "été" "🦊😀🦊" ]
if palin s$ = 1
print s$ & " is a palindrome"
else
print s$ & " is not a palindrome"
.
.
</syntaxhighlight>
 
=={{header|EchoLisp}}==
Line 1,898 ⟶ 2,018:
<syntaxhighlight lang="lisp">(defun palindrome (s)
(string= s (reverse s)))</syntaxhighlight>
 
The version below will work correctly with inexact palindromes, as defined in this exercise:
 
<syntaxhighlight lang="lisp">
(defun test-if-palindrome (text)
(setq text (replace-regexp-in-string "[[:space:][:punct:]]" "" text)) ; remove spaces and punctuation, by replacing them with nothing
(string-equal-ignore-case text (reverse text))) ; ignore case when looking at reversed text
</syntaxhighlight>
{{out}}
 
<pre>
(test-if-palindrome "A man, a plan, a canal, Panama")
t
</pre>
 
=={{header|Erlang}}==
Line 2,490 ⟶ 2,624:
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/Palindrome_detection}}
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation &mdash;i.e. XML, JSON&mdash; they are intended for storage and transfer purposes more than visualization and edition.
 
'''Solution'''
Programs in Fōrmulæ are created/edited online in its [https://formulae.org website], However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used.
 
[[File:Fōrmulæ - Palindrome detection 01.png]]
In '''[https://formulae.org/?example=Palindrome_detection this]''' page you can see the program(s) related to this task and their results.
 
[[File:Fōrmulæ - Palindrome detection 02.png]]
 
'''Test cases'''
 
[[File:Fōrmulæ - Palindrome detection 03.png]]
 
[[File:Fōrmulæ - Palindrome detection 04.png]]
 
=={{header|GAP}}==
Line 2,601 ⟶ 2,743:
return true
}</syntaxhighlight>
 
=={{header|GolfScript}}==
 
===Recursive===
 
<syntaxhighlight lang="golfscript">{.,1>{(\)@={pal}0if}1if\;}:pal;</syntaxhighlight>
 
Test program:
 
<syntaxhighlight lang="groovy">"ABBA" pal
"a" pal
"13231+464+989=989+464+13231" pal
"123 456 789 897 654 321" pal</syntaxhighlight>
 
{{out}}
<pre>1
1
1
0</pre>
 
=={{header|Groovy}}==
Line 2,762 ⟶ 2,923:
return x
end</syntaxhighlight>
 
=={{header|Insitux}}==
This function works also for vectors.
<syntaxhighlight lang="insitux">(var palindrome? (= (reverse %)))
 
(palindrome? "deified") ;returns true</syntaxhighlight>
 
Space and punctuation insensitive version:
 
<syntaxhighlight lang="insitux">(var palindrome? (comp (filter letter?) lower-case (= (reverse %))))
 
(palindrome? "In girum imus nocte et consumimur igni.") ;returns true</syntaxhighlight>
 
=={{header|Ioke}}==
Line 3,086 ⟶ 3,259:
 
=={{header|langur}}==
<syntaxhighlight lang="langur">val .ispal = ffn(.s) { len(.s) > 0 and .s == s2sreverse .s, len(.s)..1}
 
val .tests = h{
"": false,
"z": true,
Line 4,087 ⟶ 4,260:
<span style="color: #0000FF;">?</span><span style="color: #000000;">extra_credit</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"tregða, gón, reiði - er nóg að gert"</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
 
=={{header|Phixmonti}}==
<syntaxhighlight lang="Phixmonti">include ..\Utilitys.pmt
 
def palindrome? dup reverse == enddef
 
( "abba" "boom" "radar" "civic" "great" )
len for get
dup print " : palindrome? " print palindrome?
if "true" else "false" endif ?
endfor
 
def letter? dup 'z' <= swap 'a' >= and enddef
 
"" >ps
"In girum imus nocte, et consumimur igni" dup ? lower
len for get
dup letter?
if
ps> swap chain >ps
else
drop
endif
endfor
 
ps> palindrome? if "This is an inexact palindrome!" else "Not a palindrome." endif ?
</syntaxhighlight>
{{out}}
<pre>abba : palindrome? true
boom : palindrome? false
radar : palindrome? true
civic : palindrome? true
great : palindrome? false
In girum imus nocte, et consumimur igni
This is an inexact palindrome!
 
=== Press any key to exit ===</pre>
 
=={{header|PHP}}==
Line 4,999 ⟶ 5,209:
'ingirumimusnocteetconsumimurigni palindrome? n:put
</syntaxhighlight>
 
=={{header|Refal}}==
<syntaxhighlight lang="refal">$ENTRY Go {
= <Test 'rotor'>
<Test 'racecar'>
<Test 'RACEcar'>
<Test 'level'>
<Test 'rosetta'>
<Test 'A man, a plan, a canal: Panama'>
<Test 'Egad, a base tone denotes a bad age'>
<Test 'This is not a palindrome'>;
};
 
Test {
e.W, <Palindrome e.W> <InexactPalindrome e.W>: {
True s.1 = <Prout e.W ': exact palindrome'>;
s.1 True = <Prout e.W ': inexact palindrome'>;
False False = <Prout e.W ': not a palindrome'>;
};
};
 
InexactPalindrome {
e.W = <Palindrome <Filter ('ABCDEFGHIJKLMNOPQRSTUVWXYZ') <Upper e.W>>>;
};
 
Filter {
(e.Keep) = ;
(e.Keep) s.C e.W, e.Keep: {
e.1 s.C e.2 = s.C <Filter (e.Keep) e.W>;
e.1 = <Filter (e.Keep) e.W>;
};
};
 
Palindrome {
= True;
s.C = True;
s.C e.W s.C = <Palindrome e.W>;
e.X = False;
};</syntaxhighlight>
{{out}}
<pre>rotor: exact palindrome
marinus@frankenstein:~/refal$ refc palin && refgo palin
Refal-5 Compiler. Version PZ Jan 25 2024
Copyright: Refal Systems Inc.
rotor: exact palindrome
racecar: exact palindrome
RACEcar: inexact palindrome
level: exact palindrome
rosetta: not a palindrome
A man, a plan, a canal: Panama: inexact palindrome
Egad, a base tone denotes a bad age: inexact palindrome
This is not a palindrome: not a palindrome</pre>
 
=={{header|REXX}}==
Line 5,066 ⟶ 5,328:
</syntaxhighlight>
 
=={{header|RPL}}==
≪ ""
OVER SIZE 1 '''FOR''' j
OVER j DUP SUB + -1 '''STEP'''
==
≫ ‘<span style="color:blue">XPAL?</span>’ STO
====Stretch====
RPL does not support Unicode. To detect inexact palindromes, we just need a clean-up word:
≪ ""
1 3 PICK SIZE '''FOR''' j
OVER j DUP SUB
'''IF''' DUP "a" ≥ OVER "z" ≤ AND '''THEN''' NUM 32 - CHR '''END'''
'''IF''' DUP "A" ≥ OVER "Z" ≤ AND '''THEN''' + '''ELSE''' DROP '''END'''
'''NEXT''' SWAP DROP
≫ ‘<span style="color:blue">AZONLY</span>’ STO
≪ <span style="color:blue">AZONLY</span> ""
OVER SIZE 1 '''FOR''' j
OVER j DUP SUB + -1 '''STEP'''
==
≫ ‘<span style="color:blue">IPAL?</span>’ STO
 
"rotor" <span style="color:blue">XPAL?</span>
"In girum imus nocte et consumimur igni." <span style="color:blue">IPAL?</span>
{{out}}
<pre>
2: 1
1: 1
</pre>
=={{header|Ruby}}==
 
Line 5,104 ⟶ 5,395:
iterative 0.062000 0.000000 0.062000 ( 0.055000)
recursive 16.516000 0.000000 16.516000 ( 16.562000)</pre>
 
=={{header|Rhovas}}==
 
Simplest solution using <code>String.reverse</code>:
 
<syntaxhighlight lang="scala">
func isPalindromeReverse(string: String): Boolean {
return string == string.reverse();
}
</syntaxhighlight>
 
Alternate character-based solution using pattern matching. Unlike <code>String.reverse</code>, this has limited unicode support due to surrogates (code points split into multiple characters).
 
<syntaxhighlight lang="scala">
func isPalindromeChars(chars: List<String>): Boolean {
match (chars) {
[]: return true;
[elem]: return true;
[first, middle*, last]: return first == last && isPalindromeChars(middle);
}
}
</syntaxhighlight>
 
Overall result and test cases:
 
<syntaxhighlight lang="scala">
func isPalindrome(string: String): Boolean {
return isPalindromeReverse(string) && isPalindromeChars(string.chars);
}
 
assert isPalindrome("");
assert isPalindrome("f");
assert isPalindrome("noon");
assert isPalindrome("kayak");
assert isPalindrome("step on no pets");
assert !isPalindrome("palindrome");
assert !isPalindrome("A man, a plan, a canal - Panama!"); //inexact
 
assert isPalindrome("§★♖★§"); //single utf16 code points
assert isPalindromeReverse("🗲"); //string reverse handles surrogates
assert !isPalindromeChars("🗲".chars); //.chars splits surrogates into two chars
</syntaxhighlight>
 
=={{header|Run BASIC}}==
<syntaxhighlight lang="runbasic">data "My dog has fleas", "Madam, I'm Adam.", "1 on 1", "In girum imus nocte et consumimur igni"
 
for i = 1 to 4
read w$
print w$;" is ";isPalindrome$(w$);" Palindrome"
next
 
FUNCTIONfunction isPalindrome$(str$)
for i = 1 to len(str$)
a$ = upper$(mid$(str$,i,1))
if (a$ >= "A" and a$ <= "Z") or (a$ >= "0" and a$ <= "9") then b$ = b$ + a$: c$ = a$ + c$
next i
if b$ <> c$ then isPalindrome$ = "not"</syntaxhighlight>
end function</syntaxhighlight>
{{out}}
<pre>My dog has fleas is not Palindrome
Line 5,351 ⟶ 5,685:
 
'''Built-in'''
<syntaxhighlight lang="ruby">say "noon".is_palindrome; # true</syntaxhighlight>
 
'''Non-recursive'''
Line 5,365 ⟶ 5,699:
true
}
elsif (s.first  != s.last) {
false
}
else {
__FUNC__(s.ftfirst(-1, ).last(-21))
}
}</syntaxhighlight>
Line 5,658 ⟶ 5,992:
console.log(isPalindrome('Я иду с мечем судия'))
</syntaxhighlight>
 
=={{header|Uiua}}==
Does not ignore spaces.
<syntaxhighlight lang="uiua">≍⇌."tacocat"</syntaxhighlight>
 
=={{header|UNIX Shell}}==
Line 5,844 ⟶ 6,182:
 
=={{header|Wren}}==
<syntaxhighlight lang="javascriptwren">var isPal = Fn.new { |word| word == ((word.count > 0) ? word[-1..0] : "") }
 
System.print("Are the following palindromes?")
Line 6,077 ⟶ 6,415:
ld (inputbuf+1),a ; New length of text without spaces for further processing
ld b,0 ; bc now set correctly to new length
ld de,bufcont ; Set up and useruse block move
ld hl,compress
ldir
885

edits