This commit is contained in:
Ingy döt Net 2013-04-10 21:29:02 -07:00
parent 764da6cbbb
commit db842d013d
19005 changed files with 197040 additions and 7 deletions

View file

@ -0,0 +1,64 @@
'''Background'''
:This problem and challenge is inspired by one that used to be given as a challenge to students learning Icon. It was intended to be tried in Icon and another language the student was familiar with. 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 talk page if you have trouble with the site).
'''Basic problem statement:'''
:Write a program that reads lines from standard input and, upon end of file, writes the longest line to standard output.
:If there are ties for the longest line, the program writes out all the lines that tie.
:If there is no input, the program should produce no output.
'''Task'''
:Implement a solution to the basic problem that adheres to the spirit of the restrictions (see below).
:Describe how you circumvented or got around these 'restrictions' and met the 'spirit' of the challenge. Your supporting description may need to describe any challenges to interpreting the restrictions and how you made this interpretation. You should state any assumptions, warnings, or other relevant points. The central idea here is to make the task a bit more interesting by thinking outside of the box and perhaps show off the capabilities of your language in a creative way. Because there is potential for more variation between solutions, the description is key to helping others see what you've done.
:This task is likely to encourage multiple different types of solutions. They should be substantially different approaches.
Given the input:
<pre>a
bb
ccc
ddd
ee
f
ggg</pre>
The output should be (possibly rearranged):
<pre>ccc
ddd
ggg</pre>
'''Original list of restrictions:'''
:1. No comparison operators may be used.
:2. No arithmetic operations, such as addition and subtraction, may be used.
:3. The only datatypes you may use are integer and string. In particular, you may not use lists.
An additional restriction became apparent in the discussion.
:4. Do not re-read the input file. Avoid using files as a replacement for lists.
'''Intent of Restrictions'''
:Because of the variety of languages on Rosetta and the wide variety of concepts used in them there needs to be a bit of clarification and guidance here to get to the spirit of the challenge and the intent of the restrictions.
::The basic problem can be solved very conventionally and that's boring and pedestrian. The original intent here wasn't to unduly frustrate people with interpreting the restrictions, it was to get people to think outside of their particular box and have a bit of fun doing it.
::The guiding principle here should be that when using the language of your choice, try to solve this creatively showing off some of your language capabilities. If you need to bend the restrictions a bit, explain why and try to follow the intent. If you think you've implemented a 'cheat' call out the fragment yourself and ask the reader if they can spot why. If you absolutely can't get around one of the restrictions, say why in your description.
::Now having said that, the restrictions require some elaboration.
:::* 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. Representing the length of any string as a number should also be avoided. 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.
:::: To make this a bit more concrete, here are a couple of specific examples:
::::: In C, a string is an array of chars, so using a couple of arrays as strings is in the spirit while using a second array in a non-string like fashion would violate the intent.
::::: In APL or J, arrays are the core of the language so ruling them out is unfair. Meeting the spirit will come down to how they are used.
:::: Please keep in mind these are just examples and you may hit new territory finding a solution. There will be other cases like these. Explain your reasoning. You may want to open a discussion on the talk page as well.
:::* The added "No rereading" restriction is for practical reasons, re-reading stdin should be broken. I haven't outright banned the use of other files but I've discouraged them as it is basically another form of a list. Somewhere there may be a language that just sings when doing file manipulation and where that makes sense; however, for most there should be a way to accomplish without resorting to an externality.
: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.

View file

@ -0,0 +1,2 @@
---
note: Programming Challenge

View file

@ -0,0 +1,18 @@
#!/usr/bin/awk -f
BEGIN {
maxlen = 0;
lenList = 0;
}
{
if (length($0)>maxlen) {
lenList = 1;
List[lenList] = $0;
maxlen = length($0);
} else if (length($0)==maxlen)
List[++lenList]=$0;
}
END {
for (k=1; k <= lenList; k++) print List[k];
}

View file

@ -0,0 +1,43 @@
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO, Ada.Characters.Latin_1;
procedure Longest_String_Challenge is
function "+"(S: String) return Unbounded_String renames To_Unbounded_String;
Separator: constant Character := Ada.Characters.Latin_1.NUL;
procedure Funny_Stuff(B, L: in out Unbounded_String; N: Unbounded_String) is
Nat: Natural;
begin
Nat := Length(N) - Length(L);
declare
Pos: Positive;
begin
Pos := Nat;
B := N;
L := N;
exception
when Constraint_Error => B := B & Separator & N;
end;
exception
when Constraint_Error => null;
end Funny_Stuff;
Buffer: Unbounded_String := +"";
Longest: Unbounded_String := +"";
Next: Unbounded_String;
begin
while True loop
Next := + Ada.Text_IO.Get_Line;
Funny_Stuff(Buffer, Longest, Next);
end loop;
exception
when others =>
for I in To_String(Buffer)'Range loop
if To_String(Buffer)(I) = Separator then
Ada.Text_IO.New_Line;
else
Ada.Text_IO.Put(To_String(Buffer)(I));
end if;
end loop;
end Longest_String_Challenge;

View file

@ -0,0 +1,49 @@
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO, Ada.Characters.Latin_1;
procedure Longest_String_Challenge is
function "+"(S: String) return Unbounded_String renames To_Unbounded_String;
function "-"(U: Unbounded_String) return String renames To_String;
Separator: constant Character := Ada.Characters.Latin_1.NUL;
procedure Funny_Stuff(B, L: in out Unbounded_String;
N: Unbounded_String;
S, T: String) is
C: Character;
begin
if S = T then
B := B & Separator & N;
else
C:= T(T'First); -- raises Constraint_Error if T is empty
begin
C := S(S'First); -- same if S is empty
Funny_Stuff(B,L,N,S(S'First+1 .. S'Last), T(T'First+1..T'Last)); --
exception
when Constraint_Error =>
B := N;
L := N;
end;
end if;
exception
when Constraint_Error => null;
end Funny_Stuff;
Buffer: Unbounded_String := +"";
Longest: Unbounded_String := +"";
Next: Unbounded_String;
begin
while True loop
Next := + Ada.Text_IO.Get_Line;
Funny_Stuff(Buffer, Longest, Next, -Longest, -Next);
end loop;
exception
when others =>
for I in To_String(Buffer)'Range loop
if To_String(Buffer)(I) = Separator then
Ada.Text_IO.New_Line;
else
Ada.Text_IO.Put(To_String(Buffer)(I));
end if;
end loop;
end Longest_String_Challenge;

View file

@ -0,0 +1,21 @@
input =
(
a
bb
ccc
ddd
ee
f
ggg
)
longestLen := 0, buffer := ""
Loop Parse, input, `n
{
top := SubStr(buffer, 1, InStr(buffer, "`n"))
StringReplace, top, top, `n
If SubStr(A_LoopField, LongestLen) ; at least as long
buffer .= A_LoopField "`n"
If !SubStr(top, StrLen(A_LoopField)) ; longer
buffer := A_LoopField "`n", LongestLen := StrLen(A_LoopField)
}
MsgBox % buffer

View file

@ -0,0 +1,30 @@
DIM buffer% 65535
bufptr% = buffer%
longest$ = " "
ON ERROR PRINT $$buffer%; : END
REPEAT
READ A$
IF FNcmp(A$, longest$) THEN
IF FNcmp(longest$, A$) ELSE bufptr% = buffer%
longest$ = A$
$bufptr% = A$
WHILE ?bufptr%
bufptr% = FNinc(bufptr%)
ENDWHILE
?bufptr% = 10
bufptr% = FNinc(bufptr%)
ENDIF
UNTIL FALSE : REM Loops until 'Out of data' error
END
DATA a, bb, ccc, ddd, ee, f, ggg
DEF FNcmp(a$, b$) : REM Returns LEN(a$)>=LEN(b$) [if b$<>""]
LEFT$(a$, 65535) = b$
= INSTR(a$, b$)
DEF FNinc(i%) : REM Returns i%+1
FOR i% = i% TO i% : NEXT
= i%

View file

@ -0,0 +1,28 @@
#include <stdio.h>
#include <string.h>
int cmp(const char *p, const char *q)
{
while (*p && *q) p = &p[1], q = &q[1];
return *p;
}
int main()
{
char line[65536];
char buf[1000000] = {0};
char *last = buf;
char *next = buf;
while (gets(line)) {
strcat(line, "\n");
if (cmp(last, line)) continue;
if (cmp(line, last)) next = buf;
last = next;
strcpy(next, line);
while (*next) next = &next[1];
}
printf("%s", buf);
return 0;
}

View file

@ -0,0 +1,4 @@
% printf "a\nbb\nccc\nddd\nee\nf\nggg" | ./a.out
ccc
ddd
ggg

View file

@ -0,0 +1,83 @@
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int inc(int x) { return (int)&((char *)x)[1]; }
int dec(int x) { return (int)&((char *)x)[-1]; }
int gt(int x, int y)
{
while (y && x) y = dec(y), x = dec(x);
return x;
}
int eq(int x, int y)
{
return !gt(x, y) && !gt(y, x);
}
int add(int x, int y)
{
while(y) x = inc(x), y = dec(y);
return x;
}
/* strlen(a) + 1 */
int length(const char *a)
{
char *x = 0; // assuming (int)(char*)0 == 0
if (!a) return 0;
while (*a) a++, x++;
return (int)x;
}
char *str_cat(char *a, const char *b)
{
int len = add(1, add(length(a), length(b)));
if (!(a = realloc(a, len))) abort();
return strcat(a, b);
}
char *get_line(char *l, FILE *fp)
{
int c, len = 0;
char tmp[2] = {0};
*l = 0;
while ((c = fgetc(fp)) != EOF) {
*tmp = c;
len = inc(len);
l = str_cat(l, tmp);
if (eq(*tmp, '\n')) return l;
}
*tmp = '\n';
return len ? str_cat(l, tmp) : l;
}
int main()
{
int l1, l2;
char *line = malloc(1), *buf = malloc(1), *longest = malloc(1);
while (1) {
line = get_line(line, stdin);
if (!(l1 = length(line))) break;
l2 = length(longest);
if (gt(l1, l2)) {
*buf = *longest = 0;
longest = str_cat(longest, line);
} else if (gt(l2, l1)) continue;
buf = str_cat(buf, line);
}
printf("%s", buf);
free(buf);
free(longest);
free(line);
return 0;
}

View file

@ -0,0 +1,33 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int longer(const char *p, const char *q) {
while (*p && *q) p = &p[1], q = &q[1];
return *p;
}
int main() {
char line[100000];
char buf[1100001];
char *linend= &line[99999];
char *bufend= &buf[1000000];
char *last = buf;
char *next = buf;
memset(line, 1, 100000);
memset(buf, 1, 1100001);
buf[0]= buf[1100000]= 0;
while (fgets(line, 100000, stdin)) {
if (!*linend) exit(1);
if (longer(last, line)) continue;
if (!longer(bufend, line)) exit(1);
if (longer(line, last)) next = buf;
last = next;
strcpy(next, line);
while (*next) next = &next[1];
}
printf("%s", buf);
exit(0);
}

View file

@ -0,0 +1,19 @@
import std.stdio, std.array;
/// Return a.length - b.length if positive, 0 otherwise.
int longer(string a, string b) {
while (!a.empty && !b.empty)
a.popFront(), b.popFront();
return a.length;
}
void main() {
string longest, lines;
foreach (string line; stdin.lines())
if (longer(line, longest))
lines = longest = line;
else if (!longer(longest, line))
lines ~= line;
writeln(lines);
}

View file

@ -0,0 +1,44 @@
package main
import (
"bufio"
"os"
)
func main() {
in := bufio.NewReader(os.Stdin)
var blankLine = "\n"
var printLongest func(string) string
printLongest = func(candidate string) (longest string) {
longest = candidate
s, err := in.ReadString('\n')
defer func() {
recover()
defer func() {
recover()
}()
_ = blankLine[0]
func() {
defer func() {
recover()
}()
_ = s[len(longest)]
longest = s
}()
longest = printLongest(longest)
func() {
defer func() {
recover()
os.Stdout.WriteString(s)
}()
_ = longest[len(s)]
s = ""
}()
}()
_ = err.(error)
os.Stdout.WriteString(blankLine)
blankLine = ""
return
}
printLongest("")
}

View file

@ -0,0 +1,17 @@
func() {
// 1. statements executed in either case
// 2. func below is a closure that captures free variables
// now, although the defer statement keeps the function
// from running until later
defer func() {
// 5. function runs either when panic happens, or
// at the time of a normal function return.
recover() // this stops panic mode
// 6. statements executed in either case, just
// before function returns
}()
// 3. more statements executed in either case
// 4. an expression that may or may not panic
// 4a. conditional code. executed only if no panic happens
return // 7. function return happens in either case
}()

View file

@ -0,0 +1,20 @@
def longer = { a, b ->
def aa = a, bb = b
while (bb && aa) {
bb = bb.substring(1)
aa = aa.substring(1)
}
aa ? a : b
}
def longestStrings
longestStrings = { BufferedReader source, String longest = '' ->
String current = source.readLine()
def finalLongest = current == null \
? longest \
: longestStrings(source,longer(current,longest))
if (longer(finalLongest, current) == current) {
println current
}
return finalLongest
}

View file

@ -0,0 +1,9 @@
def source = new BufferedReader(new StringReader('''a
bb
ccc
ddd
ee
f
ggg'''))
longestStrings(source)

View file

@ -0,0 +1,14 @@
procedure main(arglist)
local b # the current buffer (string)
local l # the last string
local L # a \n delimited accumulation of all the longest strings
while b := read() do {
/l := b # primes l on first pass
b ? ( move(*l), if move(1) then L := (l := b) || "\n" else if move(0) then L := (\L|"") || b || "\n")
# move(*l) - fails if b is not l characters long
# move(1) - succeeds/fails if the string is longer and triggers a reset of L
}
write(\L)
end

View file

@ -0,0 +1,12 @@
procedure main()
longest(".") # needs a single character seed to throw away
end
procedure longest(Longest)
Line := read() | return Longest # read until we can return the longest strings
if Line[*Longest] then Longest := Line # prime/reset Longest
Longest := longest(Longest) # use stack to hold multiples
if Line[*Longest] then write(Line) # write only longest strings,
# Line must be at least as long as Longest
return Longest # feed back longest for length
end

View file

@ -0,0 +1,7 @@
isempty =. (0 [ 0&{) :: 1: NB. 0=#
compare =. ($:&}.)`((0 1,:_1 0) {~ <@,&isempty)@.(+.&isempty) NB. *@-&#
add =. ,`(,:@[)`] @. (compare {:)
> add&.>/ (}: , ,:&.>@{:) ;: 'a bb ccc ddd ee f ggg'
ccc
ddd
ggg

View file

@ -0,0 +1,15 @@
function longestString(file);
fid = fopen(file);
maxlen = 0; L = {};
while ~feof(fid)
line = fgetl(fid);
if (length(line)>maxlen)
maxlen = length(line);
L = {line};
elseif (length(line)==maxlen)
L{end+1} = line;
end;
end;
fclose(fid);
disp(L);
end;

View file

@ -0,0 +1,13 @@
FixedPoint[
StringReplace[#,
x : "\n" | StartOfString ~~ a : Except["\n"] ... ~~ "\n" ~~
b : Except["\n"] ... ~~ y : "\n" | EndOfString :>
x <> Switch[((#1 + #2) + Abs[#1 - #2])/2 &[StringLength@a,
StringLength@b], Except[StringLength@a], b,
Except[StringLength@b], a, _, a <> "\n" <> b] <> y] &, "a
bb
ccc
ddd
ee
f
ggg"]

View file

@ -0,0 +1,5 @@
#!/usr/bin/perl -n
END{ print $all }
substr($_, length($l)) and $all = $l = $_
or substr($l, length) or $all .= $_;

View file

@ -0,0 +1,5 @@
(mapc prinl
(maxi '((L) (length (car L)))
(by length group
(in NIL
(make (until (eof) (link (line)))) ) ) ) )

View file

@ -0,0 +1,8 @@
(let Buf NIL
(in NIL
(until (eof)
(let (Line (line) Len (length Line))
(if (assoc Len Buf)
(conc @ (cons Line))
(push 'Buf (cons Len (cons Line))) ) ) ) )
(mapc prinl (cdr (maxi car Buf))) )

View file

@ -0,0 +1,16 @@
import fileinput
# return len(a) - len(b) if positive, 0 otherwise
def longer(a, b):
while len(a) and len(b):
a, b = a[1:], b[1:]
return len(a)
longest, lines = '', ''
for x in fileinput.input():
if longer(x, longest):
lines, longest = x, x
elif not longer(longest, x):
lines += x
print(lines, end='')

View file

@ -0,0 +1,17 @@
/*REXX pgm reads a file & prints the longest [widest] record(s)/line(s).*/
!.='' /*initialize stemmed array to nul*/
fileID='LONGEST1.TXT' /*point to the input file. */
m=0
do while min(lines(fileID),1); _=linein(fileID); w=length(_)
say 'input =' _ /*display the input to terminal. */
!.w=!.w || '0a'x || _ /*build a stemmed array element. */
m=max(m,w) /*find the maximum width so far. */
end /*while min(lines(... */
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 done.*/
end /*j*/

View file

@ -0,0 +1,18 @@
/*REXX pgm reads a file & prints the longest [widest] record(s)/line(s).*/
!.='' /*initialize stemmed array to nul*/
fileID='LONGEST2.TXT' /*point to the input file. */
signal on notready /*when E-O-F is reached, jump. */
m=0 /*maximum width line so far. */
do forever; _=linein(fileID); w=length(_) /*read a line. */
say 'input =' _ /*display the input to terminal. */
!.w=!.w || '0a'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 done.*/
end /*j*/

View file

@ -0,0 +1,44 @@
/* REXX ***************************************************************
* 27.10.2010 Walter Pachl
**********************************************************************/
Parse Arg fid
If fid='' Then Do
"ALLOC FI(IN) DA('N561985.PRIV.V100(LL)') SHR REUSE"
'EXECIO * DISKR IN (STEM L. FINIS' /* read all lines */
'FREE FI(IN)'
End
Else Do
Do i=1 By 1 While lines(fid)>0
l.i=linein(fid)
End
l.0=i-1
End
maxl = 0 /* initialize maximum length */
Do i=1 To l.0 /* loop through all lines */
linl=length(l.i) /* length of current line */
Select
When linl>maxl Then Do /* line longer than preceding */
maxl=linl /* initialize maximum length */
mem.0=1 /* memory has one entry */
mem.1=l.i /* the current line */
lin.1=i /* its line number */
End
When linl=maxl Then Do /* line as long as maximum */
z=mem.0+1 /* new memory index */
mem.z=l.i /* the current line */
lin.z=i /* its line number */
mem.0=z /* memory size */
End
Otherwise /* line is shorter than max. */
Nop /* ignore */
End
End
If mem.0>0 Then Do
Say 'Maximum line length='maxl
Say ' Line Contents'
Do i=1 To mem.0
Say right(lin.i,5) mem.i
End
End
Else
Say 'No lines in input file or file does not exist'

View file

@ -0,0 +1,17 @@
# Without restrictions
BEGIN {
v = [ ]
m = 0
}
n = $_.length
if n == m then
v <<= $_
elsif n > m then
v = [$_]
m = n
end
END {
v.each { |s| puts s }
}

View file

@ -0,0 +1,16 @@
#!/usr/bin/env tclsh
set longest z
set output ""
while {[gets stdin line] != -1} {
set comparison [string repeat z [string length $line]]
if {$longest eq $comparison} {
# this line is equally long
append output $line \n
} elseif {[string match ${longest}z* $comparison]} {
# this line is longer
set longest $comparison
set output "$line\n"
}
}
puts -nonewline $output