Longest string challenge: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(45 intermediate revisions by 22 users not shown)
Line 3:
;Background:
This "longest string challenge" is inspired by a problem that used to be given to students learning Icon. Students were expected to try to solve the problem in Icon and another language with which the student was already familiar. The basic problem is quite simple; the challenge and fun part came through the introduction of restrictions. Experience has shown that the original restrictions required some adjustment to bring out the intent of the challenge and make it suitable for Rosetta Code.
 
The original programming challenge and some solutions can be found at [https://tapestry.tucson.az.us/twiki/bin/view/Main/LongestStringsPuzzle Unicon Programming TWiki / Longest Strings Puzzle]. (See notes on the talk page if you have trouble with the site).
 
 
Line 57 ⟶ 55:
 
* In general, the restrictions are meant to avoid the explicit use of these features.
* "No comparison operators may be used" - At some level there must be some test that allows the solution to get at the length and determine if one string is longer. Comparison operators, in particular any less/greater comparison should be avoided. <u>Representing the length of any string as a number should also be avoided.</u> Various approaches allow for detecting the end of a string. Some of these involve implicitly using equal/not-equal; however, explicitly using equal/not-equal should be acceptable.
* "No arithmetic operations" - Again, at some level something may have to advance through the string. Often there are ways a language can do this implicitly advance a cursor or pointer without explicitly using a +, - , ++, --, add, subtract, etc.
* The datatype restrictions are amongst the most difficult to reinterpret. In the language of the original challenge strings are atomic datatypes and structured datatypes like lists are quite distinct and have many different operations that apply to them. This becomes a bit fuzzier with languages with a different programming paradigm. The intent would be to avoid using an easy structure to accumulate the longest strings and spit them out. There will be some natural reinterpretation here.
Line 72 ⟶ 70:
At the end of the day for the implementer this should be a bit of fun. As an implementer you represent the expertise in your language, the reader may have no knowledge of your language. For the reader it should give them insight into how people think outside the box in other languages. Comments, especially for non-obvious (to the reader) bits will be extremely helpful. While the implementations may be a bit artificial in the context of this task, the general techniques may be useful elsewhere.
<br><br>
 
=={{header|Ada}}==
 
Line 79 ⟶ 77:
In order to comply with the avoidance of greater-than or less-than comparisons and iterations with operators, only Constraint_Error exception handling is used to obtain comparison of less-than, equal-to, or greater-than. With these, only the strings that are longer than previous strings and the succeeding strings, and equal in length to each other are printed. They are printed in reverse order, but this is specifically allowed by the instructions. In order to be clear to the reader, all cases of less-than, equal to, and greater-than are manually iterated through. Since equal-to/not-equal-to testing is allowed, there should be no question that a "case" statement is also allowed.
 
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO;
 
procedure Longest_Strings is
Line 223 ⟶ 221:
end if;
end;
</syntaxhighlight>
</lang>
 
The output, given the above example input, is:
Line 249 ⟶ 247:
So this is the first solution.
 
<langsyntaxhighlight Adalang="ada">with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO, Ada.Characters.Latin_1;
 
Line 300 ⟶ 298:
end if;
end loop;
end Longest_String_Challenge;</langsyntaxhighlight>
 
Output, when run with its own source code as the input:
Line 308 ⟶ 306:
Here is the second solution. It also makes heavy use of exceptions, but it does not require to compute the difference (which is an arithmetic operation, i.e., a bit of a cheat). Instead, the procedure Funny_Stuff carries some auxiliary strings S, T. If they are unequal and neither is empty, it recursively calls itself with the same strings shortened by 1. At some point of time, either S is empty, or T is empty, or both are empty.
 
<langsyntaxhighlight Adalang="ada">with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO, Ada.Characters.Latin_1;
Line 362 ⟶ 360:
end if;
end loop;
end Longest_String_Challenge;</langsyntaxhighlight>
 
The output, when given its own source code as the input:
Line 378 ⟶ 376:
 
Warts are that all input strings must be shorter than (bound -1) characters and it is assumed that ABS "1" > ABS "0"; this true for every known implementation of Algol 68.
<langsyntaxhighlight lang="algol68">
BEGIN
INT bound = 1000000; CO Arbitrary upper limit on string lengths CO
Line 416 ⟶ 414:
buffer := buffer[2 : UPB buffer] CO Step over newline CO
OD
END</langsyntaxhighlight>
{{out}}
<pre>printf "a\nbb\nccc\nddd\nee\nf\nggg\n" | a68g Longest_String.a68
Line 425 ⟶ 423:
 
Alternative recursive solution - the only standard operators used are string concatenation and array upper bound and SIGN (the signum function). Operators ATLEASTASLONGAS and LONGERTHAN are defined without the use of any comparison or arithmetic operators. The input file is processed recursively so this would run out of stack space for a large input file. Exploits some features of Algol 68 STRING slicing.
<langsyntaxhighlight lang="algol68"># The standard SIGN operator returns -1 if its operand is < 0 #
# , 0 if its operand is 0 #
# , 1 if its operand is > 0 #
Line 519 ⟶ 517:
# find the logest lines from standard inoout #
VOID( print longest lines( stand in, read line( stand in ) ) )
</syntaxhighlight>
</lang>
 
=={{header|AutoHotkey}}==
Line 528 ⟶ 526:
If the top line of the output does not contain a character at the position of the last character in this line of the input, then reset the output to be this line *and* set "LongestLength" to be the length of this line.
did I break any rules?
<langsyntaxhighlight AutoHotkeylang="autohotkey">input =
(
a
Line 548 ⟶ 546:
buffer := A_LoopField "`n", LongestLen := StrLen(A_LoopField)
}
MsgBox % buffer</langsyntaxhighlight>
 
=={{header|AWK}}==
 
<langsyntaxhighlight lang="awk">#!/usr/bin/awk -f
BEGIN {
maxlen = 0;
Line 568 ⟶ 567:
END {
for (k=1; k <= lenList; k++) print List[k];
}</langsyntaxhighlight>
 
Output:
Line 575 ⟶ 574:
ddd
ggg</pre>
 
 
=={{header|BASIC}}==
==={{header|Applesoft BASIC}}===
Only Integer and String type variables are used. It is difficult not to use floats as, unfortunately, pretty much all internal operations default to floating point in Applesoft BASIC. Most, if not all, functions in Applesoft BASIC are passed arguments and return floating point types. In the spirit of the task the INT function is used throughout.
<syntaxhighlight lang="basic"> REM CONSTANTS
100 TWO% = INT ( VAL ("2"))
REM NOT IS A "LOGICAL" OPERATOR, A NON-ARITHMETIC OPERATOR
110 UN% = NOT FALSE%
REM MSG$ = "PRESS CTRL+C THEN RETURN FOR END-OF-TEXT"
REM BUT NEED THE HIGH BIT SET, SO ASSIGN MSG$ THE TEDIOUS WAY
111 R$ = CHR$ ( INT ( VAL ("210")))
112 E$ = CHR$ ( INT ( VAL ("197")))
113 S$ = CHR$ ( INT ( VAL ("211")))
114 SPACE$ = CHR$ ( INT ( VAL ("160")))
115 C$ = CHR$ ( INT ( VAL ("195")))
116 T$ = CHR$ ( INT ( VAL ("212")))
117 N$ = CHR$ ( INT ( VAL ("206")))
118 F$ = CHR$ ( INT ( VAL ("198")))
119 HYPHEN$ = CHR$ ( INT ( VAL ("173")))
120 MSG$ = CHR$ ( INT ( VAL ("208"))) + R$ + E$ + S$ + S$ + SP$
121 MSG$ = MSG$ + C$ + T$ + R$ + CHR$ ( INT ( VAL ("204"))) + CHR$ ( INT ( VAL ("171"))) + C$ + SP$
122 MSG$ = MSG$ + T$ + CHR$ ( INT ( VAL ("200"))) + E$ + N$ + SP$
123 MSG$ = MSG$ + R$ + E$ + T$ + CHR$ ( INT ( VAL ("213"))) + R$ + N$ + SP$
124 MSG$ = MSG$ + F$ + CHR$ ( INT ( VAL ("207"))) + R$ + SP$
125 MSG$ = MSG$ + E$ + N$ + CHR$ ( INT ( VAL ("196"))) + HY$ + CHR$ ( INT ( VAL ("207"))) + F$ + HY$
126 MSG$ = MSG$ + T$ + E$ + CHR$ ( INT ( VAL ("216"))) + T$
REM OUTPUT THE MESSAGE TO THE TOP OF THE TEXT SCREEN
130 IT$ = "12345678901234567890123"
140 TEXT : HOME : VTAB TWO%: POKE 34,UN%
REM + IS A "STRING" OPERATOR, A NON-ARITHMETIC OPERATOR WHEN USED WITH STRINGS FOR CONCATENATION
150 IT$ = IT$ + "."
160 P% = INT ( VAL ("10" + STR$ ( LEN (IT$))))
170 POKE P%, INT ( ASC ( LEFT$ (MSG$,UN%)))
180 MSG$ = MID$ (MSG$,TWO%)
190 IF LEN (MSG$) GOTO 150
REM READ STDIN
200 ONERR GOTO 500"END OF DATA?
210 INPUT "";STD$
220 L% = INT ( LEN (STD$))
230 IF NOT L% GOTO 210"READ NEXT LINE IF EMPTY
250 IT$ = BIGGEST$
260 COMPARE$ = STD$
REM COMPARE WITH LONGEST STRING
270 IF INT ( LEN (COMPARE$)) GOTO 300"DECREMENT
280 IF INT ( LEN (IT$)) GOTO 210"READ NEXT LINE IF LESS THAN LONGEST STRING
REM EQUAL TO LONGEST STRING
290 RESULT$ = RESULT$ + CHR$ (INT ( VAL ("13"))) + STD$: GOTO 210"READ NEXT LINE
REM REMOVE A CHARACTER FROM BOTH IF THEY STILL HAVE LENGTH
300 IF INT ( LEN (IT$)) THEN IT$ = MID$ (IT$,TWO%):COMPARE$ = MID$ (COMPARE$,TWO%): GOTO 270"COMPARE AGAIN
REM GREATER THAN LONGEST STRING
310 BIGGEST$ = STD$
320 RESULT$ = BIGGEST$
330 GOTO 210"READ NEXT LINE
REM CATCH ERROR
500 POKE INT ( VAL ("216")),ZERO%
510 E% = INT ( PEEK ( INT ( VAL ("222"))))
REM CLEAR THE MESSAGE FROM THE TEXT SCREEN
520 V% = INT ( PEEK ( INT ( VAL ("37"))))
530 TEXT : VTAB UN%: CALL INT ( VAL ("-868"))
540 VTAB V%: CALL INT ( VAL ("-912"))
REM ERROR CODE 255
550 IT$ = "12345678901234567"
560 IT$ = IT$ + IT$ + IT$
570 IT$ = IT$ + IT$ + IT$ + IT$ + IT$
580 COMPARE$ = MID$ (IT$,UN%,E%)
REM COMPARE ERROR CODE WITH 255
590 IF INT ( LEN (COMPARE$)) GOTO 610"DECREMENT
600 RESUME
REM REMOVE A CHARACTER FROM THE ITERATOR
610 IT$ = MID$ (IT$,TWO%)
REM DONE? IF NOT DONE REMOVE A CHARACTER FROM THE ERROR CODE
620 IF INT ( LEN (IT$)) THEN COMPARE$ = MID$ (COMPARE$,TWO%): GOTO 590"COMPARE AGAIN
630 PRINT RESULT$</syntaxhighlight>
 
==={{header|BASIC256}}===
<syntaxhighlight lang="vb">dim test = {"a", "bb", "ccc", "ddd", "ee", "f", "ggg"}
test1 = ""
 
for c = 0 to test[?]-1
if length(test[c]) > length(test1) Then
test1 = test[c]
test2 = test1 & chr(10)
else
if length(test[c]) = length(test1) then test2 += test[c] & chr(10)
end if
next c
 
print test2
end</syntaxhighlight>
 
==={{header|Chipmunk Basic}}===
{{works with|Chipmunk Basic|3.6.4}}
<syntaxhighlight lang="qbasic">10 data "a","bb","ccc","ddd","ee","f","ggg","~" : ' la tilde es solo para mantener el código compacto
20 restore
30 read test$
40 if test$ = "~" then goto 70
50 if len(test$) > len(test1$) then test1$ = test$ : test2$ = test1$+chr$(10) else if len(test$) = len(test1$) then test2$ = test2$+test$+chr$(10)
60 goto 30
70 print test2$
80 end</syntaxhighlight>
 
==={{header|GW-BASIC}}===
{{works with|PC-BASIC|any}}
{{works with|BASICA}}
{{works with|Chipmunk Basic}}
{{works with|QBasic}}
<syntaxhighlight lang="qbasic">10 DATA "a","bb","ccc","ddd","ee","f","ggg","~"
20 RESTORE
30 READ TEST$
40 IF TEST$ = "~" THEN GOTO 80
50 IF LEN(TEST$) > LEN(TEST1$) THEN LET TEST1$ = TEST$ : LET TEST2$ = TEST1$ + CHR$(10) : GOTO 30
60 IF LEN(TEST$) = LEN(TEST1$) THEN LET TEST2$ = TEST2$ + TEST$ + CHR$(10)
70 GOTO 30
80 PRINT TEST2$
90 END</syntaxhighlight>
 
==={{header|MSX Basic}}===
{{works with|MSX BASIC|any}}
{{works with|Applesoft BASIC}}
<syntaxhighlight lang="qbasic">10 DATA "a","bb","ccc","ddd","ee","f","ggg","~"
30 READ T$
40 IF T$ = "~" THEN GOTO 80
50 IF LEN(T$) > LEN(T1$) THEN LET T1$ = T$ : LET T2$ = T1$ + CHR$(10) : GOTO 30
60 IF LEN(T$) = LEN(T1$) THEN LET T2$ = T2$ + T$ + CHR$(10)
70 GOTO 30
80 PRINT T2$
90 END</syntaxhighlight>
 
==={{header|QBasic}}===
{{works with|QBasic|1.1}}
{{works with|QuickBasic|4.5}}
{{trans|FreeBASIC}}
<syntaxhighlight lang="qbasic">
DO
READ test$
IF test$ = "~" THEN EXIT DO
IF LEN(test$) > LEN(test1$) THEN
test1$ = test$
test2$ = test1$ + CHR$(10)
ELSEIF LEN(test$) = LEN(test1$) THEN
LET test2$ = test2$ + test$ + CHR$(10)
END IF
LOOP
 
PRINT (test2$)
 
DATA "a", "bb", "ccc", "ddd", "ee", "f", "ggg", "~" : ' la tilde es solo para mantener el código compacto
</syntaxhighlight>
{{out}}
<pre>Igual que la entrada de FreeBASIC.</pre>
 
==={{header|True BASIC}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="basic">
DATA "a", "bb", "ccc", "ddd", "ee", "f", "ggg", "~" ! la tilde es solo para mantener el código compacto
 
DO
READ test$
IF test$ = "~" then EXIT DO
IF len(test$) > len(test1$) then
LET test1$ = test$
LET test2$ = test1$ & chr$(10)
ELSEIF len(test$) = len(test1$) then
LET test2$ = test2$ & test$ & chr$(10)
END IF
LOOP
 
PRINT(test2$)
END
</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de FreeBASIC.
</pre>
 
=={{header|BBC BASIC}}==
Key to this solution are the functions '''FNcmp''', which compares the lengths of two strings without using comparison operators, and '''FNinc''', which increments an integer without using arithmetic operators. It also strictly adheres to the requirement to use only integer and string data types (no arrays or pointers) and avoids the use of LEN.
<langsyntaxhighlight lang="bbcbasic"> DIM buffer% 65535
bufptr% = buffer%
longest$ = " "
Line 607 ⟶ 781:
DEF FNinc(i%) : REM Returns i%+1
FOR i% = i% TO i% : NEXT
= i%</langsyntaxhighlight>
Output:
<pre>
Line 614 ⟶ 788:
ggg
</pre>
 
=={{header|BQN}}==
Most primitives in BQN implicitly use comparison, so this solution avoids the several easy ways out.
 
The namespace approach keeps track of the latest string and the result without needing a list.
 
The recursion and pattern matching lets us avoid comparison operators and arithmetic.
 
The datatype restrictions are, as discussed in the problem statement, not applicable for BQN as it would unfairly rule the language out.
 
<syntaxhighlight lang="bqn">Cmp ← {
⟨⟩ 𝕊 ⟨⟩: 0; · 𝕊 ⟨⟩: 1; ⟨⟩ 𝕊 ·: 2;
𝕨 𝕊○(1⊸↓) 𝕩
}
 
cr←@+10
 
•Out {𝕊:
(•Getline@){
@ Longest 𝕩: 𝕩.str;
𝕨 Longest 𝕩:
(•Getline@) Longest 𝕨 {𝕨Cmp𝕩.curr}◶⟨
{curr⇐𝕨,str⇐𝕩.str∾cr∾𝕨}
{curr⇐𝕨,str⇐𝕨}
⟩ 𝕩
}𝕩
}{curr⇐"",str⇐""}</syntaxhighlight>
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <string.h>
Line 643 ⟶ 845:
printf("%s", buf);
return 0;
}</langsyntaxhighlight>Running it:<syntaxhighlight lang="text">% printf "a\nbb\nccc\nddd\nee\nf\nggg" | ./a.out
ccc
ddd
ggg</langsyntaxhighlight>
Note that the above code never checked for memory bounds and long input can overrun the buffers. It's intentionally made this way to keep it simple, please don't complicate it by adding safety features: if you are really concerned with that, below is a second method that can handle arbitrary length input.<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
Line 729 ⟶ 931:
 
return 0;
}</langsyntaxhighlight>
 
Here is a more concise variation which exits (with a non-zero return code) if it encounters a buffer overflow:
 
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 765 ⟶ 967:
printf("%s", buf);
exit(0);
}</langsyntaxhighlight>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">#include <iostream>
#include <string.h>
int main()
{
std::string longLine, longestLines, newLine;
 
while (std::cin >> newLine)
{
auto isNewLineShorter = longLine.c_str();
auto isLongLineShorter = newLine.c_str();
while (*isNewLineShorter && *isLongLineShorter)
{
// This determines which string is longer without using a built
// in string length function. The loop will stop at the 0 at the
// end of the shortest string.
isNewLineShorter = &isNewLineShorter[1];
isLongLineShorter = &isLongLineShorter[1];
}
 
if(*isNewLineShorter) continue; // other lines were longer, do nothing
if(*isLongLineShorter)
{
// the new string is the longest so far
longLine = newLine;
longestLines = newLine;
}
else
{
// the new string is the same lenth as the previous longest
longestLines+=newLine;
}
longestLines+="\n"; // append a new line between the strings
}
 
std::cout << "\nLongest string:\n" << longestLines;
}</syntaxhighlight>
{{out}}
<pre>
a
bb
ccc
ddd
ee
f
ggg
 
Longest string:
ccc
ddd
ggg
</pre>
 
=={{header|Clojure}}==
{{trans|Python}}
<langsyntaxhighlight lang="lisp">ns longest-string
(:gen-class))
 
Line 799 ⟶ 1,055:
(println "Input text:")
(println "Output:\n" (process))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 818 ⟶ 1,074:
=={{header|D}}==
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.array;
 
/// Return a.length - b.length if positive, 0 otherwise.
Line 836 ⟶ 1,092:
 
writeln(lines);
}</langsyntaxhighlight>
{{out}}
<pre>ccc
ddd
ggg</pre>
 
 
=={{header|FreeBASIC}}==
{{trans|PureBasic}}
<syntaxhighlight lang="freebasic">
Dim As String test, test1, test2
Data "a", "bb", "ccc", "ddd", "ee", "f", "ggg", "~" ' la tilde es solo para mantener el código compacto
 
Do
Read test
If test = "~" Then Exit Do : End If
If Len(test) > Len(test1) Then
test1 = test
test2 = test1 & Chr(10)
Elseif Len(test) = Len(test1) Then
test2 += test & Chr(10)
End If
Loop
 
Print(test2)
Sleep
</syntaxhighlight>
{{out}}
<pre>
ccc
ddd
ggg
</pre>
 
 
=={{header|FutureBasic}}==
'''Option 1 (old school)'''
<syntaxhighlight lang="futurebasic">
local fn FindLongest( test as CFArrayRef ) as CFStringRef
'~'1
CFStringRef s, t1 = @"", t2 = @""
 
for s in test
if ( len(s) > len(t1) )
t1 = s
t2 = fn StringWithFormat( @"%@\n", s )
else
if ( len(s) == len(t1) )
t2 = fn StringWithFormat( @"%@%@\n", t2, s )
end if
end if
next
end fn = t2
 
print fn FindLongest( @[@"a", @"bb", @"ccc", @"ddd", @"ee", @"f", @"ggg"] )
 
HandleEvents
</syntaxhighlight>
'''Option 2 (modern)'''
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"
 
_longestStringsToDisplay = 3
 
local fn LongestStrings( string as CFStringRef )
CFArrayRef array = fn StringComponentsSeparatedByString( string, @" " )
SortDescriptorRef sortAscending = fn SortDescriptorWithKey( @"length", YES )
array = fn ArraySortedArrayUsingDescriptors( array, @[sortAscending] )
array = fn ArraySubarrayWithRange( array, fn CFRangeMake( len(array)-_longestStringsToDisplay, _longestStringsToDisplay ) )
NSLog( @"%@\n%@\n%@", array[0], array[1], array[2] )
end fn
 
fn LongestStrings( @"a bb ccc ddd ee f ggg" )
 
HandleEvents
</syntaxhighlight>
'''Output for either:'''
<pre>
ccc
ddd
ggg
</pre>
 
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 886 ⟶ 1,220:
}
printLongest("")
}</langsyntaxhighlight>
Description: It's basically the recursion+exceptions solution used by others, but staying close to the restrictions.
 
Line 906 ⟶ 1,240:
</pre>
The above expressions avoid arithmetic, but not all comparisons, because error values are typically tested and branched on. Eliminating all comparisons leaves no boolean values in the program and no way to use if statements, which in Go require a boolean condition. Conditional flow control is implemented with the following device:
<langsyntaxhighlight lang="go">func() {
// 1. statements executed in either case
// 2. func below is a closure that captures free variables
Line 922 ⟶ 1,256:
// 4a. conditional code. executed only if no panic happens
return // 7. function return happens in either case
}()</langsyntaxhighlight>
A complication of course is that sometimes you want to conditionally execute code if the expression panics. Without a boolean value to invert, this case requires introducing an extra layer of func..defer..recover with a different expression contrived that will panic with the opposite effect.
 
=={{header|Groovy}}==
Solution: recursive
<langsyntaxhighlight lang="groovy">def longer = { a, b ->
def aa = a, bb = b
while (bb && aa) {
Line 946 ⟶ 1,280:
}
return finalLongest
}</langsyntaxhighlight>
 
Test:
<langsyntaxhighlight lang="groovy">def source = new BufferedReader(new StringReader('''a
bb
ccc
Line 957 ⟶ 1,291:
ggg'''))
 
longestStrings(source)</langsyntaxhighlight>
 
Output:
Line 963 ⟶ 1,297:
ddd
ccc</pre>
 
=={{header|Haskell}}==
 
Even though lists of strings were disallowed in the rules, I have used them instead of a file handle, mainly to keep my functions pure, and to avoid the hassle of using the IO monad for something more trivial without it.
 
Another use of lists in the code is for Strings, which are lists of Chars in Haskell by default, which made it easy to compare them by length.
 
No operators were used except for string/list concatenation.
 
<syntaxhighlight lang="haskell">
module Main where
 
import System.Environment
 
cmp :: String -> String -> Ordering
cmp [] [] = EQ
cmp [] (_:_) = LT
cmp (_:_) [] = GT
cmp (_:xs) (_:ys) = cmp xs ys
 
longest :: String -> String
longest = longest' "" "" . lines
where
longest' acc l [] = acc
longest' [] l (x:xs) = longest' x x xs
longest' acc l (x:xs) = case cmp l x of
LT -> longest' x x xs
EQ -> longest' (acc ++ '\n':x) l xs
GT -> longest' acc l xs
 
main :: IO ()
main = do
(file:_) <- getArgs
contents <- readFile file
putStrLn $ longest contents
</syntaxhighlight>
 
=={{header|Icon}} and {{header|Unicon}}==
=== String Scanning / Pattern Matching Solution ===
<langsyntaxhighlight Iconlang="icon">procedure main(arglist)
local b # the current buffer (string)
local l # the last string
Line 979 ⟶ 1,349:
write(\L)
end</langsyntaxhighlight>
 
Sample Output:<pre>ccc
Line 987 ⟶ 1,357:
=== Recursive Solution ===
Here is a recursive solution using only single character substring-ing (no string scanning/pattern matching).
<langsyntaxhighlight Iconlang="icon">procedure main()
longest(".") # needs a single character seed to throw away
end
Line 998 ⟶ 1,368:
# Line must be at least as long as Longest
return Longest # feed back longest for length
end</langsyntaxhighlight>
 
Sample Output:<pre>ggg
Line 1,006 ⟶ 1,376:
=={{header|J}}==
 
<langsyntaxhighlight lang="j"> isempty =. (0 [ 0&{) :: 1: NB. 0=#
compare =. ($:&}.)`((0 1,:_1 0) {~ <@,&isempty)@.(+.&isempty) NB. *@-&#
add =. ,`(,:@[)`] @. (compare {:)
Line 1,012 ⟶ 1,382:
ccc
ddd
ggg</langsyntaxhighlight>
 
Description:
Line 1,026 ⟶ 1,396:
=={{header|Java}}==
Translation of Python via D
<langsyntaxhighlight lang="java">import java.io.File;
import java.util.Scanner;
 
Line 1,053 ⟶ 1,423:
return false;
}
}</langsyntaxhighlight>
 
<pre>ccc
Line 1,062 ⟶ 1,432:
{{works with|Julia|0.6}}
 
<langsyntaxhighlight lang="julia">function longer(a, b)
try b[endof(a)]
b[endof(a)]
catch return true
catch
return true
end
return false
Line 1,079 ⟶ 1,451:
end
end
println(String(lines))
end
printlongest(str::String) = printlongest(IOBuffer(str))
 
const str = IOBufferprintlongest("a\nbb\nccc\nddd\nee\nf\nggg")</syntaxhighlight>
printlongest(str)</lang>
 
{{out}}
Line 1,089 ⟶ 1,461:
ddd
ggg</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.1.0
 
import java.io.File
Line 1,125 ⟶ 1,497:
// alternatively (but cheating as library functions will use comparisons and lists under the hood)
println(File("lines.txt").readLines().groupBy { it.length }.maxBy { it.key }!!.value.joinToString("\n"))
}</langsyntaxhighlight>
 
{{out}}
Line 1,137 ⟶ 1,509:
ggg
</pre>
 
=={{header|Lambdatalk}}==
<syntaxhighlight lang="scheme">
{def longest_string
{def longest_string.r
{lambda {:max :s}
{if {S.empty? {S.rest :s}}
then
else {if {= {W.length {S.first :s}} :max} then {br}{S.first :s} else}
{longest_string.r :max {S.rest :s}}}}}
{lambda {:s}
{longest_string.r {max {S.map W.length :s}} :s #}}}
-> longest_string
 
{def words a bb ccc ddd ee f ggg} // it's a sentence, not a list
-> words
 
{longest_string {words}}
->
ccc
ddd
ggg
</syntaxhighlight>
 
=={{header|Lua}}==
 
<langsyntaxhighlight lang="lua">function longer(s1, s2)
while true do
s1 = s1:sub(1, -2)
Line 1,165 ⟶ 1,560:
end
 
print(output)</langsyntaxhighlight>
 
This solution is ispired by the Python one, but since in Lua even an empty string has a boolean true value, it had to be slightly altered. Testing whether a string is empty is done by searching for the Lua string ''pattern'' <code>'^$'</code>. If it is found, i.e. the examined string is empty, <code>string.find</code> returns the position of the match, or <code>nil</code> if it didn't match. Since in Lua any number is <code>true</code>, we just test for the boolean value of the result.
 
Note that the <code>longer</code> function returns <code>true</code> even if both strings have the same length, so the return value can either be <code>true</code> or <code>false</code> and we can avoid using a comparison or equality operator in interpreting this return value.
Line 1,173 ⟶ 1,568:
The <code>longer</code> function also avoids using the length operator (<code>#</code>), because in the comments on the restrictions of this task it is stated that ''"Representing the length of any string as a number should also be avoided."''. Otherwise it could have been written shorter and faster like this:
 
<langsyntaxhighlight lang="lua">function longer(s1, s2)
if s1:sub(#s2):find('^$') then
return false
Line 1,180 ⟶ 1,575:
end
end
</syntaxhighlight>
</lang>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight lang="mathematica">FixedPoint[
StringReplace[#,
x : "\n" | StartOfString ~~ a : Except["\n"] ... ~~ "\n" ~~
Line 1,195 ⟶ 1,590:
ee
f
ggg"]</langsyntaxhighlight>
{{Out}}
<pre>ccc
Line 1,203 ⟶ 1,598:
=={{header|MATLAB}} / {{header|Octave}}==
 
<langsyntaxhighlight MATLABlang="matlab">function longestString(file);
fid = fopen(file);
maxlen = 0; L = {};
Line 1,218 ⟶ 1,613:
disp(L);
end;
</syntaxhighlight>
</lang>
 
Output:
Line 1,226 ⟶ 1,621:
[1,3] = ggg
} </pre>
 
=={{header|MiniScript}}==
{{trans|Python}}
<syntaxhighlight lang="miniscript">
string.isLonger = function(s)
return self.hasIndex(s.len)
end function
 
longest = ""
lines = ""
 
current = input
while current
if current.isLonger(longest) then
lines = current
longest = current
else if not longest.isLonger(current) then
lines += current
end if
current = input
end while
 
for i in range(0, lines.len, longest.len)
print lines[i:i + longest.len]
end for
</syntaxhighlight>
{{out}}
<pre>
a
bb
ccc
dd
eee
f
ggg
hh
 
ccc
eee
ggg
</pre>
 
=={{header|Nanoquery}}==
{{trans|Python}}
<syntaxhighlight lang="nanoquery">import Nanoquery.IO
 
def longer(a, b)
try
b[len(a)-1]
return false
catch
return true
end
end
 
print "enter filename: "
$f = new(File, input())
 
longest = ""
lines = ""
for x in $f.read()
if longer(x, longest)
lines = x
longest = x
else if !longer(longest, x)
lines += "\n" + x
end
end
 
println lines</syntaxhighlight>
{{out}}
<pre>ccc
ddd
ggg</pre>
 
=={{header|Nim}}==
To compare the length of strings, we could have use the standard function "cmp" but it would have been cheating. We could also have used the trick based on exception catching, but, in Nim, IndexError is considered as a defect and, even if in current version (1.4) IndexError is actually catchable, it would probably not still be the case in future versions.
 
So, we have used another way to compare the length of strings, clearly not efficient, but efficiency is not a goal here.
 
<syntaxhighlight lang="nim">import strutils
 
const
 
# Define int constants instead of an enum to use only ints and strings.
Shorter = -1
SameLength = 0
Longer = 1
 
type LengthComparison = range[Shorter..Longer]
 
func cmpLength(a, b: string): LengthComparison =
let a = repeat(' ', a.len)
let b = repeat(' ', b.len)
result = if a in b: (if b in a: SameLength else: Shorter) else: Longer
 
var longest = ""
var result = ""
for line in "longest_string_challenge.txt".lines:
case cmpLength(line, longest)
of Shorter:
discard
of SameLength:
result.add '\n' & line
of Longer:
longest = line
result = line
 
echo result</syntaxhighlight>
 
{{out}}
<pre>ccc
ddd
ggg</pre>
 
=={{header|OCaml}}==
Line 1,231 ⟶ 1,740:
Without the restrictions, the standard way to solve the task would be to iterate the lines, compare their length, and accumulate the longest lines in a list. Here we bypass the restriction of not using comparison operators (in the function <code>cmp</code>) by taking advantage that characters of strings are indexed from 0 to [length - 1] and trying to access to a character which index is the length of the other string (if it is beyond the end of the string an exception is raised). The other restriction of not using lists is easily bypassed by concatenating the results instead of accumulating it in a list.
 
<langsyntaxhighlight lang="ocaml">let input_line_opt ic =
try Some (input_line ic)
with End_of_file -> None
Line 1,254 ⟶ 1,763:
print_string acc
in
loop "" ""</langsyntaxhighlight>
 
=={{header|Pascal}}==
{{works with|Free_Pascal}}
In this version, inc() is used instead of additions. It still has a comparison.
<langsyntaxhighlight lang="pascal">program LongestStringChallenge_1(input, output);
 
var
Line 1,295 ⟶ 1,804:
writeln (lines[position]);
end;
end.</langsyntaxhighlight>
Output:
<pre>% ./LongestStringChallenge_1
Line 1,313 ⟶ 1,822:
{{libheader|SysUtils}}
This version uses range check exceptions for the comparisons of string lengths. The range checks are compiler specific. With FreePascal its requires the use of the type ANSIstring instead of "classic" type string.
<langsyntaxhighlight lang="pascal">program LongestStringChallenge_2(input, output);
 
{$mode ObjFPC}
Line 1,355 ⟶ 1,864:
writeln (lines[position]);
end;
end.</langsyntaxhighlight>
Output:
<pre>% ./LongestStringChallenge_2
Line 1,372 ⟶ 1,881:
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">#!/usr/bin/perl -n
END{ print $all }
 
substr($_, length($l)) and $all = $l = $_
or substr($l, length) or $all .= $_;</langsyntaxhighlight>
 
=={{header|Perl 6Phix}}==
A recursive/substring based approach, I can't see any explicit maths/comparisons anyway.<br>
Since file i/o is not permitted in a browser, for running under pwa/p2js this fakes it using the first 40 words from unix_dict(), the longest word/line being (appropriately enough) "abbreviate".
Technically of course that uses a list, but not really in a way that goes against the spirit of the task.
I should probably note that while desktop/Phix copes fine with the full list of 25107 words, that would run out of memory/exceed the call stack under pwa/p2js using this particular (highly-callstack-abusive) method.<br>
The original file i/o has been left in as comments, in case you want to test that when running on desktop/Phix.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #000080;font-style:italic;">--integer fn = open(command_line()[2],"r") -- (reading the source file)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">unix_dict</span><span style="color: #0000FF;">()[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">40</span><span style="color: #0000FF;">]&-</span><span style="color: #000000;">1</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">allx</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">line</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">line</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'x'</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">line</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">longest</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">mask</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- object line = gets(fn)</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">];</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$];</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">mask</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">newmask</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">allx</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mask</span><span style="color: #0000FF;">,</span><span style="color: #000000;">newmask</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">longest</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mask</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">mask</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">longest</span><span style="color: #0000FF;">(</span><span style="color: #000000;">newmask</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mask</span><span style="color: #0000FF;">,</span><span style="color: #000000;">newmask</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- puts(1,line)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">mask</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">longest</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"x"</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--close(fn)</span>
<!--</syntaxhighlight>-->
Of course it is just a thinly disguised version of:
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">function</span> <span style="color: #000000;">longest</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">gets</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">line</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">l</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">longest</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">longest</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">line</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">l</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">longest</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
 
=={{header|PHP}}==
<lang perl6>my $l = ''; # Sample longest string seen.
my $a = ''; # Accumulator to save longest strings.
 
<syntaxhighlight lang="php"><?php
while get() -> $s {
my $n = "$s\n";
if $n.substr($l.chars) { # Is new string longer?
$a = $l = $n; # Reset accumulator.
}
elsif !$l.substr($n.chars) { # Same length?
$a ~= $n; # Accumulate it.
}
}
print $a;</lang>
 
echo 'Enter strings (empty string to finish) :', PHP_EOL;
Given the example input, returns:
<pre>ccc
ddd
ggg</pre>
 
$output = $previous = readline();
=={{header|Phix}}==
while ($current = readline()) {
A recursive/substring based approach, I can't see any explicit maths/comparisons anyway:
$p = $previous;
<lang Phix>integer fn = open(command_line()[2],"r") -- (reading the source file)
$c = $current;
// Remove first character from strings until one of them is empty
while ($p and $c) {
$p = substr($p, 1);
$c = substr($c, 1);
}
// If $p and $c are empty : strings are of equal length
if (!$p and !$c) {
$output .= PHP_EOL . $current;
}
// If $c is not empty, $current is longer
if ($c) {
$output = $previous = $current;
}
}
 
echo 'Longest string(s) = ', PHP_EOL, $output, PHP_EOL;</syntaxhighlight>
function allx(string line)
line[1..-1] = 'x'
return line
end function
 
{{out}}
function longest(string mask)
<pre>Enter strings (empty string to finish) :
object line = gets(fn)
a
string newmask
bb
if atom(line) then return mask end if
ccc
newmask = allx(line)
ddd
if not match(mask,newmask) then return longest(mask) end if
ee
mask = longest(newmask)
f
if match(mask,newmask) then
ggg
puts(1,line)
end if
return mask
end function
 
Longest string(s) =
?longest("x")
ccc
 
ddd
close(fn)
ggg</langpre>
Of course it is just a thinly disguised version of:
<lang Phix>function longest(integer l)
object line = gets(fn)
if line=-1 then return l end if
if l>length(line) then return longest(l) end if
l = longest(length(line))
if l=length(line) then
puts(1,line)
end if
return l
end function
 
?longest(0)</lang>
 
=={{header|PicoLisp}}==
Not sure if this meets the spirit. I would implement it the same way if there were no "restrictions":
<langsyntaxhighlight PicoLisplang="picolisp">(mapc prinl
(maxi '((L) (length (car L)))
(by length group
(in NIL
(make (until (eof) (link (line)))) ) ) ) )</langsyntaxhighlight>
Another solution avoids 'group', and builds an associative buffer of lines instead:
<langsyntaxhighlight PicoLisplang="picolisp">(let Buf NIL
(in NIL
(until (eof)
Line 1,454 ⟶ 1,994:
(conc @ (cons Line))
(push 'Buf (cons Len (cons Line))) ) ) ) )
(mapc prinl (cdr (maxi car Buf))) )</langsyntaxhighlight>
 
=={{header|Pike}}==
Line 1,468 ⟶ 2,008:
 
<code>return -1;</code> starts the backend, which allows pike to execute the remaining call_outs and exit.
<langsyntaxhighlight Pikelang="pike">int main(int argc, array argv)
{
string longest = "";
Line 1,487 ⟶ 2,027:
call_out(exit, 0.01, 0);
return -1;
}</langsyntaxhighlight>
 
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">
<lang PL/I>
read: procedure options (main); /* 18 January 2012. */
declare line character (100) varying controlled;
Line 1,530 ⟶ 2,070:
 
end read;
</syntaxhighlight>
</lang>
output (the above file plus the following 3 lines):
<pre>
Line 1,540 ⟶ 2,080:
=={{header|PowerShell}}==
{{works with|PowerShell|2}}
<syntaxhighlight lang="powershell">
<lang PowerShell>
# Get-Content strips out any type of line break and creates an array of strings
# We'll join them back together and put a specific type of line break back in
Line 1,581 ⟶ 2,121:
# Output longest strings
$LongestStrings.Split( "`n" )
</syntaxhighlight>
</lang>
 
===PowerShell Alternate Version===
The list restrictions should not apply here because this is essentially one line of code using only the input and no variables.
<syntaxhighlight lang="powershell">
<lang PowerShell>
@'
a
Line 1,598 ⟶ 2,138:
Sort-Object -Property Name -Descending |
Select-Object -Property Count, @{Name="Length"; Expression={[int]$_.Name}}, Group -First 1
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 1,607 ⟶ 2,147:
 
=={{header|PureBasic}}==
<langsyntaxhighlight lang="purebasic">
 
Procedure.i ConsoleWrite(t.s) ; compile using /CONSOLE option
Line 1,654 ⟶ 2,194:
StdOut(a$)
 
</syntaxhighlight>
</lang>
 
;Output:
Line 1,675 ⟶ 2,215:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">import fileinput
 
# This returns True if the second string has a value on the
Line 1,696 ⟶ 2,236:
lines += x
 
print(lines, end='')</langsyntaxhighlight>
 
;Sample runs:
Line 1,718 ⟶ 2,258:
 
</pre>
 
=={{header|Quackery}}==
 
The quandary here is, is a dynamic array a list? If yes, then nothing is allowed, as the only composite structure in Quackery is the dynamic array ("nest" in Quackery jargon), including code, and Quackery is one of those languages where code is data, and data is code. If no, then everything is allowed and the exercise is trivial. So, in the spirit of the task we will differentiate between strings (in reality nests of numbers interpreted as ascii characters) and other nests, and use only strings where the context is clearly data.
 
We note that implicit arithmetic is allowable, so the use of <code>witheach</code> to iterate over a string is permitted.
 
'''Method'''
 
<code>comparison</code> compares the length of two strings on the top of second on stack, designated A and B here, without using comparisons.
 
From A we construct a string A' of the same length as A consisting entirely of 0s (i.e. the control code "nul"), which will later be taken to indicate that A is the longer string of the two. From B we construct a string B' of the same length consisting entirely of 1s (i.e. the control code "soh"), which will later be taken to indicate that A is the longer string of the two. 2 ("stx" will indicate that the two strings are the same length.)
 
We reduce the length of A' by the number of characters in B' by repeatedly removing the last character from A' using <code>-1 split drop</code>, once for each character in B'. If B' is longer than A' this will leave an empty string. (The way <code>split</code> operates means that attempting to separate the last character from an empty string will return two empty strings, and not raise an error.
 
Then we do the same but reducing the length of B' by the length of A' (the original A', before its length was reduced.)
 
At this point, either A' or B' will be an empty string if one was longer than the other, or both will be empty strings if they were the same length initially. We concatenate them, then concatenate a 2, and return the first character in the resultant string, i.e. 0, 1, or 2.
 
<code>task</code> prompts the user to input strings, using the result of <code>comparison</code> to determine when the user ends inputting, by indexing into an embedded lookup table and performing the specified action. It also constructs a result string consisting of the longest input strings separated by carriage returns in the same manner. Finally it prints the result string.
 
<syntaxhighlight lang="Quackery"> [ 0 ] is alonger
[ 1 ] is blonger
[ 2 ] is a&bsame
 
[ [] swap witheach
[ drop blonger join ]
[] rot witheach
[ drop alonger join ]
over dip dup
witheach [ drop -1 split drop ]
unrot
witheach [ drop -1 split drop ]
join
a&bsame join
0 peek ] is comparison ( $ $ --> c )
 
[ say "Enter an empty string to end."
cr cr
$ "" $ ""
[ $ "Enter a string: " input
dup $ "" comparison
[ table
true true false ] do while
carriage join
2dup comparison
[ table
[ drop ]
[ dip [ 2drop $ "" ] ]
[ dip join ] ]
do again ]
cr say "Result:" cr
drop join echo$ ] is task ( --> )</syntaxhighlight>
 
{{out}}
 
Aa a dialogue in the Quackery shell (REPL):
<pre>/O> task
...
Enter an empty string to end.
 
Enter a string: a
Enter a string: bb
Enter a string: ccc
Enter a string: ddd
Enter a string: ee
Enter a string: f
Enter a string: ggg
Enter a string:
 
Result:
ccc
ddd
ggg
</pre>
 
 
=={{header|Racket}}==
This is an attempt to follow the problem restrictions: use just one list of the complete output (so it's not used as a container of strings), and the work is done by manipulating this list vs the input instead of direct comparisons.
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 1,736 ⟶ 2,352:
[(newline? o) (loop O C i:rI rO i:rI)]
[else (loop O (cdr C) i:rI rO i:rC)])))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
 
<syntaxhighlight lang="raku" line>my $l = ''; # Sample longest string seen.
my $a = ''; # Accumulator to save longest strings.
 
while get() -> $s {
my $n = "$s\n";
if $n.substr($l.chars) { # Is new string longer?
$a = $l = $n; # Reset accumulator.
}
elsif !$l.substr($n.chars) { # Same length?
$a ~= $n; # Accumulate it.
}
}
print $a;</syntaxhighlight>
 
Given the example input, returns:
<pre>ccc
ddd
ggg</pre>
 
=={{header|REXX}}==
In the REXX language, &nbsp; ''everything'' &nbsp; is a string (characters).
===read file until not ready===
<br>A stemmed array (y.1 y.2 y.3 ∙∙∙) is nothing more than three disjointed REXX variables.
This REXX version adheres to spirit (and letter) of all the restrictions for this task:
===read file until E-O-F===
::* &nbsp; no comparators are used, &nbsp; including those within:
<lang rexx>/*REXX program reads a file and prints the longest [widest] record(s)/line(s). */
::::* &nbsp; &nbsp;&nbsp; '''if''' &nbsp; &nbsp; &nbsp; (statements)
!.= /*initialize the stemmed array to nul. */
fileID=::::* 'LONGEST1.TXT'&nbsp; '''when''' &nbsp; /*the name of the file used for input. */(statements)
m=0::::* &nbsp; '''until''' &nbsp;&nbsp; /*the maximum width (so farclauses). &nbsp; and */
::::* &nbsp; do while min( lines(fileID), 1) '''while''' /*form to bypass using conditional test*/ &nbsp;&nbsp;(clauses)
::* &nbsp; no output is produced when the file is empty &nbsp; (or contains all null strings),
_=linein(fileID); w=length(_) /*obtain a line; obtain the width(len).*/
::* &nbsp; no arrays or lists are used,
say 'input =' _ /*display the line to the terminal. */
::* &nbsp; no additions or subtractions are used, &nbsp; and
!.w=!.w || '0a'x || _ /*build a stemmed array element. */
::* &nbsp; no variables are used to hold the length of (any) record.
m=max(m, w) /*determine the maximum width so far. */
<syntaxhighlight lang="rexx">/*REXX program reads a file and displays the longest [widest] record(s) [line(s)]. */
end /*while*/
signal on notReady /*when E-O-F is reached, jump/branch. */
 
do jiFID=m for m 'LONGEST.TXT' /*handle the casedefault offile noidentifier for input. */
parse arg fid . /*obtain optional argument from the CL.*/
say center(' longest record(s): ', 79, '═')
do #=1 to length(fid); iFID=fid /*Specified? Then use what's given. */
say substr(!.m, 2)
end /*#*/
say center(' list end ' , 79, '═')
!= exit /*stickthe maximum width (so far). a fork in it, we're all done. */
do forever; _=linein(iFID); ?=_ /*read a line from the input file. */
end /*j*/</lang>
t=0 /*don't do the initialization next time*/
{{out|output|text=&nbsp; when using the default input:}}
do #=t for t; !=?; ?=; $=. || _; end /*just do 1st time.*/
do #=length(!' ') to length(?) for 1; $=; end /*found widest rec.*/
do #=length(!) to length(?) for 1; $=$'a0d'x || _; end /*append it to $. */
/* [↑] variable # isn't really used.*/
!=left(., max( length(!), length(?) ) ) /*!: is the max length record, so far.*/
end /*forever*/
/* [↓] comes here when file gets E─O─F*/
notReady: do j=length(!) to length(!) for length(!) /*handle the case of no input*/
say substr($, 2) /*display (all) the longest records. */
end /*j*/ /*stick a fork in it, we're all done. */</syntaxhighlight>
{{out|input|text=file &nbsp; '''LONGEST.TXT''':}}
<pre>
a
input = a
bb
input = bb
input = ccc
input = ddd
input = ee
input = f
input = ggg
═════════════════════════════ longest record(s): ══════════════════════════════
ccc
ddd
ee
f
ggg
══════════════════════════════════ list end ═══════════════════════════════════
</pre>
 
===read file until not ready===
<lang rexx>/*REXX program reads a file and prints the longest [widest] record(s)/line(s). */
!.= /*initialize the stemmed array to nul. */
fileID= 'LONGEST2.TXT' /*the name of the file used for input. */
signal on notReady /*when E-O-F is reached, jump/branch. */
m=0 /*the maximum width (so far). */
 
do forever; _=linein(fileID); w=length(_) /*read a line from the input file. */
say 'input =' _ /*display line's content to terminal. */
!.w=!.w || 'a'x || _ /*build a stemmed array element. */
m=max(m, w) /*find the maximum width so far. */
end /*forever*/
 
notReady: do j=m for m /*handle the case of no input. */
say center(' longest record(s): ', 79, '═')
say substr(!.m, 2)
say center(' list end ' , 79, '═')
exit /*stick a fork in it, we're all done. */
end /*j*/</lang>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
ccc
input = -3
ddd
input = -two
ggg
input = -one
input = zero
input = one
input = two
input = three
input = ?
input = four
input = five
input = six
input = seven
input = eight
input = nine
input = ten
input = √121
input = 12.+0
═════════════════════════════ longest record(s): ══════════════════════════════
three
seven
eight
12.+0
══════════════════════════════════ list end ═══════════════════════════════════
</pre>
 
===Dual code (works on TSO and PC)===
<langsyntaxhighlight lang="rexx">/* REXX ***************************************************************
* 27.10.2010 Walter Pachl
**********************************************************************/
Line 1,865 ⟶ 2,469:
End
Else
Say 'No lines in input file or file does not exist' </langsyntaxhighlight>
<pre>
Maximum line length=5
Line 1,874 ⟶ 2,478:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Longest string challenge
# Date : 2017/10/11
# Author : Gal Zsolt (~ CalmoSoft ~)
# Email : <calmosoft@gmail.com>
 
load "stdlib.ring"
Line 1,901 ⟶ 2,502:
test2 = sort(test2)
see test2 + nl
</syntaxhighlight>
</lang>
Output:
<pre>
Line 1,907 ⟶ 2,508:
ddd
ggg
</pre>
 
=={{header|RPL}}==
This program complies with the list of restrictions:
The main hack is based on the fact that the <code>SUB</code> function, which extracts one or more characters from a string, returns the null character if its arguments exceed the size of the string. It is then easy to compare lengths without any comparison operator.
 
A second hack is to use a string to count the number of compliant strings already in the stack: the <code>+</code> and <code>STO+</code> commands present in the code are not arithmetic operations, but string operations aiming at appending characters.
 
The user stack is both the standard input and output.
{{works with|HP|49}}
≪ "X" → count
≪ 1 CF <span style="color:grey">@ flag 1 set means there are at least 2 strings in the stack</span>
'''WHILE''' "String?" "" INPUT DUP SIZE '''REPEAT'''
'''IF''' 1 FS? '''THEN'''
'''CASE'''
DUP2 SWAP SIZE DUP SUB NUM NOT '''THEN'''
DROP '''END'''
DUP2 SIZE DUP SUB NUM NOT '''THEN'''
count "X" + SIZE ROLLD count SIZE DROPN "X" 'count' STO '''END'''
"X" 'count' STO+
'''END'''
'''ELSE''' 1 SF '''END'''
'''END''' DROP
≫ ≫ '<span style="color:blue">TASK</span>' STO
 
<span style="color:blue">TASK</span>
"a" "bb" "ccc" "ddd" "ee" "f" "ggg" ""
{{out}}
<pre>
3: "ccc"
2: "ddd"
1: "ggg"
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby"># Without restrictions
BEGIN {
v = [ ]
Line 1,926 ⟶ 2,559:
END {
v.each { |s| puts s }
}</langsyntaxhighlight>
 
Then ''ruby -n longest.rb < file.txt''
<langsyntaxhighlight lang="ruby">h = $stdin.group_by(&:size)
puts h.max.last unless h.empty?</langsyntaxhighlight>
This uses a hash with arrays as values - but not explicit.
 
=={{header|Run BASIC}}==
Uses in memory database
<langsyntaxhighlight lang="runbasic">sqliteconnect #mem, ":memory:" ' Create in memory DB
#mem execute("CREATE TABLE data(str)") ' And fields to hold the string data
 
Line 1,951 ⟶ 2,584:
str$ = #row str$()
print leng;" ";str$ ' print the data
WEND</langsyntaxhighlight>
 
Using a simple sort method
 
<langsyntaxhighlight lang="runbasic">strings$ = "a bb ccc ddd ee f ggg" ' The given string data
 
while word$(strings$,numWords + 1," ") <> "" ' Count the words
Line 1,980 ⟶ 2,613:
for i = 1 to numWords
print len(string$(i));" ";string$(i) ' print out the words in length descending sequence
next i</langsyntaxhighlight>
<pre>3 ccc
3 ddd
Line 1,988 ⟶ 2,621:
1 a
1 f</pre>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">use std::cmp::Ordering;
use std::io::BufRead;
 
/// Compares the length of two strings by iterating over their characters
/// together until either string has run out.
fn compare(a: &str, b: &str) -> Ordering {
let mut a = a.chars();
let mut b = b.chars();
loop {
match (a.next(), b.next()) {
(None, None) => return Ordering::Equal,
(Some(_), None) => return Ordering::Greater,
(None, Some(_)) => return Ordering::Less,
(Some(_), Some(_)) => {}
}
}
}
 
/// Returns the longest lines of the input, separated by newlines.
fn longest<I: IntoIterator<Item = String>>(input: I) -> String {
let mut longest = String::new();
let mut output = String::new();
 
for line in input {
match compare(&line, &longest) {
// A longer string replaces the output and longest.
Ordering::Greater => {
output.clear();
output.push_str(&line);
longest = line;
}
// A string of the same length is appended to the output.
Ordering::Equal => {
output.push('\n');
output.push_str(&line);
}
// A shorter string is ignored.
Ordering::Less => {}
}
}
 
output
}
 
fn main() {
let stdin = std::io::stdin();
let lines = stdin.lock().lines().map(|l| l.expect("Failed to read."));
println!("{}", longest(lines))
}</syntaxhighlight>
 
=={{header|Scala}}==
<langsyntaxhighlight Scalalang="scala">val longest = scala.io.Source.fromFile(args.head).getLines.toIterable.groupBy(_.length).max._2
println(longest mkString "\n")</langsyntaxhighlight>
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">var l = ''; # Sample longest string seen.
var a = ''; # Accumulator to save longest strings.
 
Line 2,001 ⟶ 2,687:
}
 
print a;</langsyntaxhighlight>
 
=={{header|Tcl}}==
Uses only string comparisons for equality and glob-style matching
 
<langsyntaxhighlight lang="tcl">#!/usr/bin/env tclsh
 
set longest z
Line 2,021 ⟶ 2,707:
}
}
puts -nonewline $output</langsyntaxhighlight>
 
Test:
Line 2,047 ⟶ 2,733:
The solution uses the Mid function to compare string lengths.
 
<syntaxhighlight lang="vb">
<lang vb>
'Read the input file. This assumes that the file is in the same
'directory as the script.
Line 2,073 ⟶ 2,759:
objfile.Close
Set objfso = Nothing
</syntaxhighlight>
</lang>
 
{{Out}}
Line 2,080 ⟶ 2,766:
ddd
ggg
</pre>
 
=={{header|Wren}}==
{{trans|D}}
<syntaxhighlight lang="wren">import "io" for Stdin
 
// Return a.length - b.length if positive, 0 otherwise.
var longer = Fn.new { |a, b|
while (!a.isEmpty && !b.isEmpty) {
a = a[1..-1]
b = b[1..-1]
}
return a.count
}
 
var longest = ""
var lines = ""
var line
while ((line = Stdin.readLine()) != "") {
if (longer.call(line, longest) != 0) {
lines = longest = line
} else if (longer.call(longest, line) == 0) {
lines = "%(lines)\n%(line)"
}
}
System.print(lines)</syntaxhighlight>
 
{{out}}
<pre>
ccc
ddd
ggg
</pre>
 
=={{header|XQuery}}==
 
Port of XSLT solution, this time using a string sequence.
 
<syntaxhighlight lang="xquery">
let $seq as xs:string+ := ("a","bb","ccc","ddd","ee","f","ggg")
for $l in max(
for $s in $seq
return string-length($s)
)
return $seq[string-length(.) eq $l]
</syntaxhighlight>
 
Result:
<pre>
("ccc","ddd","ggg")
</pre>
 
=={{header|XSLT 2.0}}==
This XSLT 2.0 style-sheet...
<syntaxhighlight lang="text"><xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" encoding="UTF-8" omit-xml-declaration="yes" />
<xsl:template match="/*">
Line 2,090 ⟶ 2,826:
return s[string-length(.) eq $l]" /></t>
</xsl:template>
</xsl:stylesheet></langsyntaxhighlight>
 
...when applied to this input...
<syntaxhighlight lang="text"><t>
<s>a</s>
<s>bb</s>
Line 2,101 ⟶ 2,837:
<s>f</s>
<s>ggg</s>
</t></langsyntaxhighlight>
 
...yields...
<syntaxhighlight lang="text"><t>
<s>ccc</s>
<s>ddd</s>
<s>ggg</s>
</t></langsyntaxhighlight>
 
 
=={{header|Yabasic}}==
{{trans|FreeBASIC}}
<syntaxhighlight lang="yabasic">
data "a", "bb", "ccc", "ddd", "ee", "f", "ggg", "~"
 
do
read test$
if test$ = "~" then break : fi
if len(test$) > len(test1$) then
test1$ = test$
test2$ = test1$ + chr$(10)
elsif len(test$) = len(test1$) then
test2$ = test2$ + test$ + chr$(10)
end if
loop
 
print(test2$)
end
</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de FreeBASIC.
</pre>
 
 
=={{header|zkl}}==
Line 2,114 ⟶ 2,876:
 
To decide which of two strings is longer, a character is removed from each until one is empty. If one still has text, it is longer.
<langsyntaxhighlight lang="zkl">fcn longer(a,b){ //-->0,1,2 (same, a longer, b longer)
while(a and b){a=a.del(0); b=b.del(0);}
if (not a and not b) return(0); // a & b same length
Line 2,129 ⟶ 2,891:
} //switch
}
println(text);</langsyntaxhighlight>
{{out}}
<pre>
9,482

edits