A-M baby
This commit is contained in:
parent
764da6cbbb
commit
db842d013d
19005 changed files with 197040 additions and 7 deletions
9
Task/Multisplit/0DESCRIPTION
Normal file
9
Task/Multisplit/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
It is often necessary to split a string into pieces based on several different (potentially multi-character) separator strings, while still retaining the information about which separators were present in the input. This is particularly useful when doing small parsing tasks. The task is to write code to demonstrate this.
|
||||
|
||||
The function (or procedure or method, as appropriate) should take an input string and an ordered collection of separators. The order of the separators is significant: The delimiter order represents priority in matching, with the first defined delimiter having the highest priority. In cases where there would be an ambiguity as to which separator to use at a particular point (e.g., because one separator is a prefix of another) the separator with the highest priority should be used. Delimiters can be reused and the output from the function should be an ordered sequence of substrings.
|
||||
|
||||
Test your code using the input string “<code>a!===b=!=c</code>” and the separators “<code>==</code>”, “<code>!=</code>” and “<code>=</code>”.
|
||||
|
||||
For these inputs the string should be parsed as <code>"a" (!=) "" (==) "b" (=) "" (!=) "c"</code>, where matched delimiters are shown in parentheses, and separated strings are quoted, so our resulting output is <code>"a", empty string, "b", empty string, "c"</code>. Note that the quotation marks are shown for clarity and do not form part of the output.
|
||||
|
||||
'''Extra Credit:''' provide information that indicates which separator was matched at each separation point and where in the input string that separator was matched.
|
||||
81
Task/Multisplit/Ada/multisplit.ada
Normal file
81
Task/Multisplit/Ada/multisplit.ada
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
with Ada.Containers.Indefinite_Doubly_Linked_Lists;
|
||||
with Ada.Text_IO;
|
||||
|
||||
procedure Multisplit is
|
||||
package String_Lists is new Ada.Containers.Indefinite_Doubly_Linked_Lists
|
||||
(Element_Type => String);
|
||||
use type String_Lists.Cursor;
|
||||
|
||||
function Split
|
||||
(Source : String;
|
||||
Separators : String_Lists.List)
|
||||
return String_Lists.List
|
||||
is
|
||||
Result : String_Lists.List;
|
||||
Next_Position : Natural := Source'First;
|
||||
Prev_Position : Natural := Source'First;
|
||||
Separator_Position : String_Lists.Cursor;
|
||||
Separator_Length : Natural;
|
||||
Changed : Boolean;
|
||||
begin
|
||||
loop
|
||||
Changed := False;
|
||||
Separator_Position := Separators.First;
|
||||
while Separator_Position /= String_Lists.No_Element loop
|
||||
Separator_Length :=
|
||||
String_Lists.Element (Separator_Position)'Length;
|
||||
if Next_Position + Separator_Length - 1 <= Source'Last
|
||||
and then Source
|
||||
(Next_Position .. Next_Position + Separator_Length - 1) =
|
||||
String_Lists.Element (Separator_Position)
|
||||
then
|
||||
if Next_Position > Prev_Position then
|
||||
Result.Append
|
||||
(Source (Prev_Position .. Next_Position - 1));
|
||||
end if;
|
||||
Result.Append (String_Lists.Element (Separator_Position));
|
||||
Next_Position := Next_Position + Separator_Length;
|
||||
Prev_Position := Next_Position;
|
||||
Changed := True;
|
||||
exit;
|
||||
end if;
|
||||
Separator_Position := String_Lists.Next (Separator_Position);
|
||||
end loop;
|
||||
if not Changed then
|
||||
Next_Position := Next_Position + 1;
|
||||
end if;
|
||||
if Next_Position > Source'Last then
|
||||
Result.Append (Source (Prev_Position .. Source'Last));
|
||||
exit;
|
||||
end if;
|
||||
end loop;
|
||||
return Result;
|
||||
end Split;
|
||||
|
||||
Test_Input : constant String := "a!===b=!=c";
|
||||
Test_Separators : String_Lists.List;
|
||||
Test_Result : String_Lists.List;
|
||||
Pos : String_Lists.Cursor;
|
||||
begin
|
||||
Test_Separators.Append ("==");
|
||||
Test_Separators.Append ("!=");
|
||||
Test_Separators.Append ("=");
|
||||
Test_Result := Split (Test_Input, Test_Separators);
|
||||
Pos := Test_Result.First;
|
||||
while Pos /= String_Lists.No_Element loop
|
||||
Ada.Text_IO.Put (" " & String_Lists.Element (Pos));
|
||||
Pos := String_Lists.Next (Pos);
|
||||
end loop;
|
||||
Ada.Text_IO.New_Line;
|
||||
-- other order of separators
|
||||
Test_Separators.Clear;
|
||||
Test_Separators.Append ("=");
|
||||
Test_Separators.Append ("!=");
|
||||
Test_Separators.Append ("==");
|
||||
Test_Result := Split (Test_Input, Test_Separators);
|
||||
Pos := Test_Result.First;
|
||||
while Pos /= String_Lists.No_Element loop
|
||||
Ada.Text_IO.Put (" " & String_Lists.Element (Pos));
|
||||
Pos := String_Lists.Next (Pos);
|
||||
end loop;
|
||||
end Multisplit;
|
||||
24
Task/Multisplit/BBC-BASIC/multisplit.bbc
Normal file
24
Task/Multisplit/BBC-BASIC/multisplit.bbc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
DIM sep$(2)
|
||||
sep$() = "==", "!=", "="
|
||||
PRINT "String splits into:"
|
||||
PRINT FNmultisplit("a!===b=!=c", sep$(), FALSE)
|
||||
PRINT "For extra credit:"
|
||||
PRINT FNmultisplit("a!===b=!=c", sep$(), TRUE)
|
||||
END
|
||||
|
||||
DEF FNmultisplit(s$, d$(), info%)
|
||||
LOCAL d%, i%, j%, m%, p%, o$
|
||||
p% = 1
|
||||
REPEAT
|
||||
m% = LEN(s$)
|
||||
FOR i% = 0 TO DIM(d$(),1)
|
||||
d% = INSTR(s$, d$(i%), p%)
|
||||
IF d% IF d% < m% m% = d% : j% = i%
|
||||
NEXT
|
||||
IF m% < LEN(s$) THEN
|
||||
o$ += """" + MID$(s$, p%, m%-p%) + """"
|
||||
IF info% o$ += " (" + d$(j%) + ") " ELSE o$ += ", "
|
||||
p% = m% + LEN(d$(j%))
|
||||
ENDIF
|
||||
UNTIL m% = LEN(s$)
|
||||
= o$ + """" + MID$(s$, p%) + """"
|
||||
18
Task/Multisplit/Bracmat/multisplit.bracmat
Normal file
18
Task/Multisplit/Bracmat/multisplit.bracmat
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
( ( oneOf
|
||||
= operator
|
||||
. !arg:%?operator ?arg
|
||||
& ( @(!sjt:!operator ?arg)&(!operator.!arg)
|
||||
| oneOf$!arg
|
||||
)
|
||||
)
|
||||
& "a!===b=!=c":?unparsed
|
||||
& "==" "!=" "=":?operators
|
||||
& whl
|
||||
' ( @( !unparsed
|
||||
: ?nonOp [%(oneOf$!operators:(?operator.?unparsed))
|
||||
)
|
||||
& put$(!nonOp str$("{" !operator "} "))
|
||||
)
|
||||
& put$!unparsed
|
||||
& put$\n
|
||||
);
|
||||
19
Task/Multisplit/C++/multisplit.cpp
Normal file
19
Task/Multisplit/C++/multisplit.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include <iostream>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <string>
|
||||
|
||||
int main( ) {
|
||||
std::string str( "a!===b=!=c" ) , output ;
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer ;
|
||||
boost::char_separator<char> separator ( "==" , "!=" ) , sep ( "!" ) ;
|
||||
tokenizer mytok( str , separator ) ;
|
||||
tokenizer::iterator tok_iter = mytok.begin( ) ;
|
||||
for ( ; tok_iter != mytok.end( ) ; ++tok_iter )
|
||||
output.append( *tok_iter ) ;
|
||||
tokenizer nexttok ( output , sep ) ;
|
||||
for ( tok_iter = nexttok.begin( ) ; tok_iter != nexttok.end( ) ;
|
||||
++tok_iter )
|
||||
std::cout << *tok_iter << " " ;
|
||||
std::cout << '\n' ;
|
||||
return 0 ;
|
||||
}
|
||||
57
Task/Multisplit/C-sharp/multisplit.cs
Normal file
57
Task/Multisplit/C-sharp/multisplit.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Multisplit
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
foreach (var s in "a!===b=!=c".Multisplit(true, "==", "!=", "=")) // Split the string and return the separators.
|
||||
{
|
||||
Console.Write(s); // Write the returned substrings and separators to the console.
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
private static IEnumerable<string> Multisplit(this string s, bool returnSeparators = false,
|
||||
params string[] delimiters)
|
||||
{
|
||||
var currentString = new StringBuilder(); /* Initiate the StringBuilder. This will hold the current string to return
|
||||
* once we find a separator. */
|
||||
|
||||
int index = 0; // Initiate the index counter at 0. This tells us our current position in the string to read.
|
||||
|
||||
while (index < s.Length) // Loop through the string.
|
||||
{
|
||||
// This will get the highest priority separator found at the current index, or null if there are none.
|
||||
string foundDelimiter =
|
||||
(from delimiter in delimiters
|
||||
where s.Length >= index + delimiter.Length &&
|
||||
s.Substring(index, delimiter.Length) == delimiter
|
||||
select delimiter).FirstOrDefault();
|
||||
|
||||
if (foundDelimiter != null)
|
||||
{
|
||||
yield return currentString.ToString(); // Return the current string.
|
||||
if (returnSeparators) // Return the separator, if the user specified to do so.
|
||||
yield return
|
||||
string.Format("{{\"{0}\", ({1}, {2})}}",
|
||||
foundDelimiter,
|
||||
index, index + foundDelimiter.Length);
|
||||
currentString.Clear(); // Clear the current string.
|
||||
index += foundDelimiter.Length; // Move the index past the current separator.
|
||||
}
|
||||
else
|
||||
{
|
||||
currentString.Append(s[index++]); // Add the character at this index to the current string.
|
||||
}
|
||||
}
|
||||
|
||||
if (currentString.Length > 0)
|
||||
yield return currentString.ToString(); // If we have anything left over, return it.
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Task/Multisplit/C/multisplit-1.c
Normal file
24
Task/Multisplit/C/multisplit-1.c
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void parse_sep(const char *str, const char *const *pat, int len)
|
||||
{
|
||||
int i, slen;
|
||||
while (*str != '\0') {
|
||||
for (i = 0; i < len || !putchar(*(str++)); i++) {
|
||||
slen = strlen(pat[i]);
|
||||
if (strncmp(str, pat[i], slen)) continue;
|
||||
printf("{%.*s}", slen, str);
|
||||
str += slen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const char *seps[] = { "==", "!=", "=" };
|
||||
parse_sep("a!===b=!=c", seps, 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
1
Task/Multisplit/C/multisplit-2.c
Normal file
1
Task/Multisplit/C/multisplit-2.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
a{!=}{==}b{=}{!=}c
|
||||
30
Task/Multisplit/CoffeeScript/multisplit.coffee
Normal file
30
Task/Multisplit/CoffeeScript/multisplit.coffee
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
multi_split = (text, separators) ->
|
||||
# Split text up, using separators to break up text and discarding
|
||||
# separators.
|
||||
#
|
||||
# Returns an array of strings, which can include empty strings when
|
||||
# separators are found either adjacent to each other or at the
|
||||
# beginning/end of the text.
|
||||
#
|
||||
# Separators have precedence, according to their order in the array,
|
||||
# and each separator should be at least one character long.
|
||||
result = []
|
||||
i = 0
|
||||
s = ''
|
||||
while i < text.length
|
||||
found = false
|
||||
for separator in separators
|
||||
if text.substring(i, i + separator.length) == separator
|
||||
found = true
|
||||
i += separator.length
|
||||
result.push s
|
||||
s = ''
|
||||
break
|
||||
if !found
|
||||
s += text[i]
|
||||
i += 1
|
||||
result.push s
|
||||
result
|
||||
|
||||
console.log multi_split 'a!===b=!=c', ['==', '!=', '='] # [ 'a', '', 'b', '', 'c' ]
|
||||
console.log multi_split '', ['whatever'] # [ '' ]
|
||||
38
Task/Multisplit/D/multisplit.d
Normal file
38
Task/Multisplit/D/multisplit.d
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import std.stdio, std.array, std.algorithm;
|
||||
|
||||
string[] multiSplit(in string s, in string[] divisors)
|
||||
/*pure nothrow*/ {
|
||||
string[] result;
|
||||
auto rest = s.idup;
|
||||
|
||||
while (true) {
|
||||
bool done = true;
|
||||
string delim;
|
||||
{
|
||||
string best;
|
||||
foreach (div; divisors) {
|
||||
const maybe = find(rest, div);
|
||||
if (maybe.length > best.length) {
|
||||
best = maybe;
|
||||
delim = div;
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
result.length++;
|
||||
if (done) {
|
||||
result[$ - 1] = rest.idup;
|
||||
return result;
|
||||
} else {
|
||||
const t = findSplit(rest, delim);
|
||||
result[$ - 1] = t[0].idup;
|
||||
rest = t[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
immutable s = "a!===b=!=c";
|
||||
immutable divs = ["==", "!=", "="];
|
||||
writeln(multiSplit(s, divs).join(" {} "));
|
||||
}
|
||||
26
Task/Multisplit/Go/multisplit.go
Normal file
26
Task/Multisplit/Go/multisplit.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ms(txt string, sep []string) (ans []string) {
|
||||
for txt > "" {
|
||||
sepMatch := ""
|
||||
posMatch := len(txt)
|
||||
for _, s := range sep {
|
||||
if p := strings.Index(txt, s); p >= 0 && p < posMatch {
|
||||
sepMatch = s
|
||||
posMatch = p
|
||||
}
|
||||
}
|
||||
ans = append(ans, txt[:posMatch])
|
||||
txt = txt[posMatch+len(sepMatch):]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Printf("%q\n", ms("a!===b=!=c", []string{"==", "!=", "="}))
|
||||
}
|
||||
21
Task/Multisplit/Icon/multisplit.icon
Normal file
21
Task/Multisplit/Icon/multisplit.icon
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
procedure main()
|
||||
s := "a!===b=!=c"
|
||||
# just list the tokens
|
||||
every writes(multisplit(s,["==", "!=", "="])," ") | write()
|
||||
|
||||
# list tokens and indices
|
||||
every ((p := "") ||:= t := multisplit(s,sep := ["==", "!=", "="])) | break write() do
|
||||
if t == !sep then writes(t," (",*p+1-*t,") ") else writes(t," ")
|
||||
|
||||
end
|
||||
|
||||
procedure multisplit(s,L)
|
||||
s ? while not pos(0) do {
|
||||
t := =!L | 1( arb(), match(!L)|pos(0) )
|
||||
suspend t
|
||||
}
|
||||
end
|
||||
|
||||
procedure arb()
|
||||
suspend .&subject[.&pos:&pos <- &pos to *&subject + 1]
|
||||
end
|
||||
12
Task/Multisplit/J/multisplit-1.j
Normal file
12
Task/Multisplit/J/multisplit-1.j
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
multisplit=:4 :0
|
||||
'sep begin'=.|:t=. y /:~&.:(|."1)@;@(i.@#@[ ,.L:0"0 I.@E.L:0) x
|
||||
end=. begin + sep { #@>y
|
||||
last=.next=.0
|
||||
r=.2 0$0
|
||||
while.next<#begin do.
|
||||
r=.r,.(last}.x{.~next{begin);next{t
|
||||
last=.next{end
|
||||
next=.1 i.~(begin>next{begin)*.begin>:last
|
||||
end.
|
||||
r=.r,.'';~last}.x
|
||||
)
|
||||
19
Task/Multisplit/J/multisplit-2.j
Normal file
19
Task/Multisplit/J/multisplit-2.j
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
S=:'a!===b=!=c'
|
||||
S multisplit '==';'!=';'='
|
||||
┌───┬───┬───┬───┬─┐
|
||||
│a │ │b │ │c│
|
||||
├───┼───┼───┼───┼─┤
|
||||
│1 1│0 3│2 6│1 7│ │
|
||||
└───┴───┴───┴───┴─┘
|
||||
S multisplit '=';'!=';'=='
|
||||
┌───┬───┬───┬───┬───┬─┐
|
||||
│a │ │ │b │ │c│
|
||||
├───┼───┼───┼───┼───┼─┤
|
||||
│1 1│0 3│0 4│0 6│1 7│ │
|
||||
└───┴───┴───┴───┴───┴─┘
|
||||
'X123Y' multisplit '1';'12';'123';'23';'3'
|
||||
┌───┬───┬─┐
|
||||
│X │ │Y│
|
||||
├───┼───┼─┤
|
||||
│0 1│3 2│ │
|
||||
└───┴───┴─┘
|
||||
8
Task/Multisplit/JavaScript/multisplit.js
Normal file
8
Task/Multisplit/JavaScript/multisplit.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
RegExp.escape = function(text) {
|
||||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
}
|
||||
|
||||
multisplit = function(string, seps) {
|
||||
var sep_regex = RegExp(_.map(seps, function(sep) { return RegExp.escape(sep); }).join('|'));
|
||||
return string.split(sep_regex);
|
||||
}
|
||||
1
Task/Multisplit/Mathematica/multisplit.mathematica
Normal file
1
Task/Multisplit/Mathematica/multisplit.mathematica
Normal file
|
|
@ -0,0 +1 @@
|
|||
StringSplit["a!===b=!=c", {"==", "!=", "="}]
|
||||
11
Task/Multisplit/Perl/multisplit.pl
Normal file
11
Task/Multisplit/Perl/multisplit.pl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/perl -w
|
||||
use strict ;
|
||||
sub multisplit {
|
||||
my ( $string , $pattern ) = @_ ;
|
||||
split( /($pattern)/, $string, -1 ) ;
|
||||
}
|
||||
|
||||
my $phrase = "a!===b=!=c" ;
|
||||
my $pattern = "==|!=|=" ;
|
||||
print "$_ ," foreach multisplit( $phrase , $pattern ) ;
|
||||
print "\n" ;
|
||||
19
Task/Multisplit/PicoLisp/multisplit.l
Normal file
19
Task/Multisplit/PicoLisp/multisplit.l
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
(de multisplit (Str Sep)
|
||||
(setq Sep (mapcar chop Sep))
|
||||
(make
|
||||
(for (S (chop Str) S)
|
||||
(let L
|
||||
(make
|
||||
(loop
|
||||
(T (find head Sep (circ S))
|
||||
(link
|
||||
(list
|
||||
(- (length Str) (length S))
|
||||
(pack (cut (length @) 'S)) ) ) )
|
||||
(link (pop 'S))
|
||||
(NIL S (link NIL)) ) )
|
||||
(link (pack (cdr (rot L))))
|
||||
(and (car L) (link @)) ) ) ) )
|
||||
|
||||
(println (multisplit "a!===b=!=c" '("==" "!=" "=")))
|
||||
(println (multisplit "a!===b=!=c" '("=" "!=" "==")))
|
||||
40
Task/Multisplit/Prolog/multisplit.pro
Normal file
40
Task/Multisplit/Prolog/multisplit.pro
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
multisplit(_LSep, '') -->
|
||||
{!},
|
||||
[].
|
||||
|
||||
multisplit(LSep, T) -->
|
||||
{next_sep(LSep, T, [], Token, Sep, T1)},
|
||||
( {Token \= '' },[Token], {!}; []),
|
||||
( {Sep \= '' },[Sep], {!}; []),
|
||||
multisplit(LSep, T1).
|
||||
|
||||
next_sep([], T, Lst, Token, Sep, T1) :-
|
||||
% if we can't find any separator, the game is over
|
||||
( Lst = [] ->
|
||||
Token = T, Sep = '', T1 = '';
|
||||
|
||||
% we sort the list to get nearest longest separator
|
||||
predsort(my_sort, Lst, [(_,_, Sep)|_]),
|
||||
atomic_list_concat([Token|_], Sep, T),
|
||||
atom_concat(Token, Sep, Tmp),
|
||||
atom_concat(Tmp, T1, T)).
|
||||
|
||||
next_sep([HSep|TSep], T, Lst, Token, Sep, T1) :-
|
||||
sub_atom(T, Before, Len, _, HSep),
|
||||
next_sep(TSep, T, [(Before, Len,HSep) | Lst], Token, Sep, T1).
|
||||
|
||||
next_sep([_HSep|TSep], T, Lst, Token, Sep, T1) :-
|
||||
next_sep(TSep, T, Lst, Token, Sep, T1).
|
||||
|
||||
|
||||
my_sort(<, (N1, _, _), (N2, _, _)) :-
|
||||
N1 < N2.
|
||||
|
||||
my_sort(>, (N1, _, _), (N2, _, _)) :-
|
||||
N1 > N2.
|
||||
|
||||
my_sort(>, (N, N1, _), (N, N2, _)) :-
|
||||
N1 < N2.
|
||||
|
||||
my_sort(<, (N, N1, _), (N, N2, _)) :-
|
||||
N1 > N2.
|
||||
15
Task/Multisplit/Python/multisplit-1.py
Normal file
15
Task/Multisplit/Python/multisplit-1.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
>>> import re
|
||||
>>> def ms2(txt="a!===b=!=c", sep=["==", "!=", "="]):
|
||||
if not txt or not sep:
|
||||
return []
|
||||
ans = m = []
|
||||
for m in re.finditer('(.*?)(?:' + '|'.join('('+re.escape(s)+')' for s in sep) + ')', txt):
|
||||
ans += [m.group(1), (m.lastindex-2, m.start(m.lastindex))]
|
||||
if m and txt[m.end(m.lastindex):]:
|
||||
ans += [txt[m.end(m.lastindex):]]
|
||||
return ans
|
||||
|
||||
>>> ms2()
|
||||
['a', (1, 1), '', (0, 3), 'b', (2, 6), '', (1, 7), 'c']
|
||||
>>> ms2(txt="a!===b=!=c", sep=["=", "!=", "=="])
|
||||
['a', (1, 1), '', (0, 3), '', (0, 4), 'b', (0, 6), '', (1, 7), 'c']
|
||||
24
Task/Multisplit/Python/multisplit-2.py
Normal file
24
Task/Multisplit/Python/multisplit-2.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
>>> def ms(txt="a!===b=!=c", sep=["==", "!=", "="]):
|
||||
if not txt or not sep:
|
||||
return []
|
||||
size = [len(s) for s in sep]
|
||||
ans, pos0 = [], 0
|
||||
def getfinds():
|
||||
return [(-txt.find(s, pos0), -sepnum, size[sepnum])
|
||||
for sepnum, s in enumerate(sep)
|
||||
if s in txt[pos0:]]
|
||||
|
||||
finds = getfinds()
|
||||
while finds:
|
||||
pos, snum, sz = max(finds)
|
||||
pos, snum = -pos, -snum
|
||||
ans += [ txt[pos0:pos], [snum, pos] ]
|
||||
pos0 = pos+sz
|
||||
finds = getfinds()
|
||||
if txt[pos0:]: ans += [ txt[pos0:] ]
|
||||
return ans
|
||||
|
||||
>>> ms()
|
||||
['a', [1, 1], '', [0, 3], 'b', [2, 6], '', [1, 7], 'c']
|
||||
>>> ms(txt="a!===b=!=c", sep=["=", "!=", "=="])
|
||||
['a', [1, 1], '', [0, 3], '', [0, 4], 'b', [0, 6], '', [1, 7], 'c']
|
||||
67
Task/Multisplit/Python/multisplit-3.py
Normal file
67
Task/Multisplit/Python/multisplit-3.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
def min_pos(List):
|
||||
return List.index(min(List))
|
||||
|
||||
def find_all(S, Sub, Start = 0, End = -1, IsOverlapped = 0):
|
||||
Res = []
|
||||
if End == -1:
|
||||
End = len(S)
|
||||
if IsOverlapped:
|
||||
DeltaPos = 1
|
||||
else:
|
||||
DeltaPos = len(Sub)
|
||||
Pos = Start
|
||||
while True:
|
||||
Pos = S.find(Sub, Pos, End)
|
||||
if Pos == -1:
|
||||
break
|
||||
Res.append(Pos)
|
||||
Pos += DeltaPos
|
||||
return Res
|
||||
|
||||
def multisplit(S, SepList):
|
||||
SepPosListList = []
|
||||
SLen = len(S)
|
||||
SepNumList = []
|
||||
ListCount = 0
|
||||
for i, Sep in enumerate(SepList):
|
||||
SepPosList = find_all(S, Sep, 0, SLen, IsOverlapped = 1)
|
||||
if SepPosList != []:
|
||||
SepNumList.append(i)
|
||||
SepPosListList.append(SepPosList)
|
||||
ListCount += 1
|
||||
if ListCount == 0:
|
||||
return [S]
|
||||
MinPosList = []
|
||||
for i in range(ListCount):
|
||||
MinPosList.append(SepPosListList[i][0])
|
||||
SepEnd = 0
|
||||
MinPosPos = min_pos(MinPosList)
|
||||
Res = []
|
||||
while True:
|
||||
Res.append( S[SepEnd : MinPosList[MinPosPos]] )
|
||||
Res.append([SepNumList[MinPosPos], MinPosList[MinPosPos]])
|
||||
SepEnd = MinPosList[MinPosPos] + len(SepList[SepNumList[MinPosPos]])
|
||||
while True:
|
||||
MinPosPos = min_pos(MinPosList)
|
||||
if MinPosList[MinPosPos] < SepEnd:
|
||||
del SepPosListList[MinPosPos][0]
|
||||
if len(SepPosListList[MinPosPos]) == 0:
|
||||
del SepPosListList[MinPosPos]
|
||||
del MinPosList[MinPosPos]
|
||||
del SepNumList[MinPosPos]
|
||||
ListCount -= 1
|
||||
if ListCount == 0:
|
||||
break
|
||||
else:
|
||||
MinPosList[MinPosPos] = SepPosListList[MinPosPos][0]
|
||||
else:
|
||||
break
|
||||
if ListCount == 0:
|
||||
break
|
||||
Res.append(S[SepEnd:])
|
||||
return Res
|
||||
|
||||
|
||||
S = "a!===b=!=c"
|
||||
multisplit(S, ["==", "!=", "="]) # output: ['a', [1, 1], '', [0, 3], 'b', [2, 6], '', [1, 7], 'c']
|
||||
multisplit(S, ["=", "!=", "=="]) # output: ['a', [1, 1], '', [0, 3], '', [0, 4], 'b', [0, 6], '', [1, 7], 'c']
|
||||
26
Task/Multisplit/REXX/multisplit.rexx
Normal file
26
Task/Multisplit/REXX/multisplit.rexx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*REXX program to split a string based on different separator strings. */
|
||||
parse arg ? /*get string from command line. */
|
||||
if ?=='' then ? = 'a!===b=!=c' /*None specified? Use default.*/
|
||||
say 'old string='? /*echo the old string to screen. */
|
||||
zz = '0'x /*null char, can be most anything*/
|
||||
seps = '== != =' /*a list of seperaters to be used*/
|
||||
|
||||
do j=1 for words(seps) /*parse string with all the seps.*/
|
||||
sep=word(seps,j) /*pick a separater to use now. */
|
||||
|
||||
do k=1 for length(sep) /*parse for various sep versions.*/
|
||||
sep=strip(insert(zz,sep,k),,zz) /*allow imbedded "nulls" in sep. */
|
||||
?=changestr(sep,?,zz) /* ··· but not trailing "nulls". */
|
||||
|
||||
do until ?==??; ??=? /*keep changing until no more chg*/
|
||||
?=changestr(zz || zz, ?, zz) /*reduce replicated "nulls". */
|
||||
end /*until···*/
|
||||
|
||||
sep=changestr(zz, sep, '') /*remove true nulls from the sep.*/
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
|
||||
showNull = ' {} ' /*one last change, allow the ... */
|
||||
?=changestr(zz,?,showNull) /*showing of "null" characters. */
|
||||
say 'new string='? /*now, show and tell time. */
|
||||
/*stick a fork in it, we're done.*/
|
||||
14
Task/Multisplit/Ruby/multisplit-1.rb
Normal file
14
Task/Multisplit/Ruby/multisplit-1.rb
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
text = 'a!===b=!=c'
|
||||
separators = ['==', '!=', '=']
|
||||
|
||||
def multisplit_simple(text, separators)
|
||||
sep_regex = Regexp.new(separators.collect {|sep| Regexp.escape(sep)}.join('|'))
|
||||
text.split(sep_regex)
|
||||
end
|
||||
|
||||
p multisplit_simple(text, separators)
|
||||
["a", "", "b", "", "c"]
|
||||
=> nil
|
||||
p multisplit_simple(text, ['=', '!=', '=='])
|
||||
["a", "", "", "b", "", "c"]
|
||||
=> nil
|
||||
18
Task/Multisplit/Ruby/multisplit-2.rb
Normal file
18
Task/Multisplit/Ruby/multisplit-2.rb
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
def multisplit(text, separators)
|
||||
sep_regex = Regexp.new(separators.collect {|sep| Regexp.escape(sep)}.join('|'))
|
||||
separator_info = []
|
||||
pieces = []
|
||||
i = prev = 0
|
||||
while i = text.index(sep_regex, i)
|
||||
separator = Regexp.last_match(0)
|
||||
pieces << text[prev .. i-1]
|
||||
separator_info << [separator, i]
|
||||
i = i + separator.length
|
||||
prev = i
|
||||
end
|
||||
pieces << text[prev .. -1]
|
||||
[pieces, separator_info]
|
||||
end
|
||||
|
||||
p multisplit(text, separators)
|
||||
# => [["a", "", "b", "", "c"], [["!=", 1], ["==", 3], ["=", 6], ["!=", 7]]]
|
||||
7
Task/Multisplit/Ruby/multisplit-3.rb
Normal file
7
Task/Multisplit/Ruby/multisplit-3.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
def multisplit_rejoin(info)
|
||||
str = info[0].zip(info[1])[0..-2].inject("") {|str, (piece, (sep, idx))| str << piece << sep}
|
||||
str << info[0].last
|
||||
end
|
||||
|
||||
p multisplit_rejoin(multisplit(text, separators)) == text
|
||||
# => true
|
||||
16
Task/Multisplit/Scala/multisplit.scala
Normal file
16
Task/Multisplit/Scala/multisplit.scala
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import scala.annotation.tailrec
|
||||
def multiSplit(str:String, sep:Seq[String])={
|
||||
def findSep(index:Int)=sep find (str startsWith (_, index))
|
||||
@tailrec def nextSep(index:Int):(Int,Int)=
|
||||
if(index>str.size) (index, 0) else findSep(index) match {
|
||||
case Some(sep) => (index, sep.size)
|
||||
case _ => nextSep(index + 1)
|
||||
}
|
||||
def getParts(start:Int, pos:(Int,Int)):List[String]={
|
||||
val part=str slice (start, pos._1)
|
||||
if(pos._2==0) List(part) else part :: getParts(pos._1+pos._2, nextSep(pos._1+pos._2))
|
||||
}
|
||||
getParts(0, nextSep(0))
|
||||
}
|
||||
|
||||
println(multiSplit("a!===b=!=c", Seq("!=", "==", "=")))
|
||||
5
Task/Multisplit/Tcl/multisplit-1.tcl
Normal file
5
Task/Multisplit/Tcl/multisplit-1.tcl
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
proc simplemultisplit {text sep} {
|
||||
set map {}; foreach s $sep {lappend map $s "\uffff"}
|
||||
return [split [string map $map $text] "\uffff"]
|
||||
}
|
||||
puts [simplemultisplit "a!===b=!=c" {"==" "!=" "="}]
|
||||
14
Task/Multisplit/Tcl/multisplit-2.tcl
Normal file
14
Task/Multisplit/Tcl/multisplit-2.tcl
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
proc multisplit {text sep} {
|
||||
foreach s $sep {lappend sr [regsub -all {\W} $s {\\&}]}
|
||||
set sepRE [join $sr "|"]
|
||||
set pieces {}
|
||||
set match {}
|
||||
set start 0
|
||||
while {[regexp -indices -start $start -- $sepRE $text found]} {
|
||||
lassign $found x y
|
||||
lappend pieces [string range $text $start [expr {$x-1}]]
|
||||
lappend match [lsearch -exact $sep [string range $text {*}$found]] $x
|
||||
set start [expr {$y + 1}]
|
||||
}
|
||||
return [list [lappend pieces [string range $text $start end]] $match]
|
||||
}
|
||||
5
Task/Multisplit/Tcl/multisplit-3.tcl
Normal file
5
Task/Multisplit/Tcl/multisplit-3.tcl
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
set input "a!===b=!=c"
|
||||
set matchers {"==" "!=" "="}
|
||||
lassign [multisplit $input $matchers] substrings matchinfo
|
||||
puts $substrings
|
||||
puts $matchinfo
|
||||
Loading…
Add table
Add a link
Reference in a new issue