new tasks

This commit is contained in:
Ingy döt Net 2013-04-09 00:46:50 -07:00
parent 2a4d27cea0
commit 80737d5a6a
1194 changed files with 15353 additions and 1 deletions

View file

@ -0,0 +1,14 @@
Many languages have powerful and useful ('''binary safe''') [[wp:String (computer science)|string]] [[wp:Comparison of programming languages (string functions)|manipulation functions]], while others don't, making it harder for these languages to accomplish some tasks.
This task is about creating functions to handle ''binary'' strings (strings made of arbitrary bytes, i.e. ''byte strings'' according to Wikipedia) for those languages that don't have built-in support for them. If your language of choice does have this built-in support, show a possible alternative implementation for the ''functions'' or ''abilities'' already provided by the language.
In particular the functions you need to create are:
* String creation and destruction (when needed and if there's no [[garbage collection]] or similar mechanism)
* String assignment
* String comparison
* String cloning and copying
* Check if a string is empty
* Append a byte to a string
* Extract a substring from a string
* Replace every occurrence of a byte (or a string) in a string with another string
* Join strings
Possible contexts of use: compression algorithms (like [[LZW compression]]), L-systems (manipulation of symbols), many more.

View file

@ -0,0 +1,2 @@
---
note: String manipulation

View file

@ -0,0 +1,13 @@
10 REM create two strings
20 LET s$ = "Hello"
30 LET t$ = "Bob"
40 REM choose any random character
50 LET c = INT(RND*256)
60 REM add the character to the string
70 LET s$ = s$ + CHR$(c)
80 REM check if the string is empty
90 IF s$ = "" THEN PRINT "String is empty"
100 REM compare two strings
110 IF s$ = t$ THEN PRINT "Strings are the same"
120 REM print characters 2 to 4 of a string (a substring)
130 PRINT s$(2 TO 4)

View file

@ -0,0 +1,138 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct str_t {
size_t len, alloc;
unsigned char *s;
} bstr_t, *bstr;
#define str_len(s) ((s)->len)
bstr str_new(size_t len)
{
bstr s = malloc(sizeof(bstr_t));
if (len < 8) len = 8;
s->alloc = len;
s->s = malloc(len);
s->len = 0;
return s;
}
void str_extend(bstr s)
{
size_t ns = s->alloc * 2;
if (ns - s->alloc > 1024) ns = s->alloc + 1024;
s->s = realloc(s->s, ns);
s->alloc = ns;
}
void str_del(bstr s)
{
free(s->s), free(s);
}
int str_cmp(bstr l, bstr r)
{
int res, len = l->len;
if (len > r->len) len = r->len;
if ((res = memcmp(l->s, r->s, len))) return res;
return l->len > r->len ? 1 : -1;
}
bstr str_dup(bstr src)
{
bstr x = str_new(src->len);
memcpy(x->s, src->s, src->len);
x->len = src->len;
return x;
}
bstr str_from_chars(const char *t)
{
if (!t) return str_new(0);
size_t l = strlen(t);
bstr x = str_new(l + 1);
x->len = l;
memcpy(x->s, t, l);
return x;
}
void str_append(bstr s, unsigned char b)
{
if (s->len >= s->alloc) str_extend(s);
s->s[s->len++] = b;
}
bstr str_substr(bstr s, int from, int to)
{
if (!to) to = s->len;
if (from < 0) from += s->len;
if (from < 0 || from >= s->len)
return 0;
if (to < from) to = from + 1;
bstr x = str_new(to - from);
x->len = to - from;
memcpy(x->s, s->s + from, x->len);
return x;
}
bstr str_cat(bstr s, bstr s2)
{
while (s->alloc < s->len + s2->len) str_extend(s);
memcpy(s->s + s->len, s2->s, s2->len);
s->len += s2->len;
return s;
}
void str_swap(bstr a, bstr b)
{
size_t tz;
unsigned char *ts;
tz = a->alloc; a->alloc = b->alloc; b->alloc = tz;
tz = a->len; a->len = b->len; b->len = tz;
ts = a->s; a->s = b->s; b->s = ts;
}
bstr str_subst(bstr tgt, bstr pat, bstr repl)
{
bstr tmp = str_new(0);
int i;
for (i = 0; i + pat->len <= tgt->len;) {
if (memcmp(tgt->s + i, pat->s, pat->len)) {
str_append(tmp, tgt->s[i]);
i++;
} else {
str_cat(tmp, repl);
i += pat->len;
if (!pat->len) str_append(tmp, tgt->s[i++]);
}
}
while (i < tgt->len) str_append(tmp, tgt->s[i++]);
str_swap(tmp, tgt);
str_del(tmp);
return tgt;
}
void str_set(bstr dest, bstr src)
{
while (dest->len < src->len) str_extend(dest);
memcpy(dest->s, src->s, src->len);
dest->len = src->len;
}
int main()
{
bstr s = str_from_chars("aaaaHaaaaaFaaaaHa");
bstr s2 = str_from_chars("___.");
bstr s3 = str_from_chars("");
str_subst(s, s3, s2);
printf("%.*s\n", s->len, s->s);
str_del(s);
str_del(s2);
str_del(s3);
return 0;
}

View file

@ -0,0 +1,6 @@
: empty? ( str len -- ? ) nip 0= ;
: +c ( c str len -- ) + c! ;
: replace-bytes ( from to str len -- )
bounds do
over i c@ = if dup i c! then
loop 2drop ;

View file

@ -0,0 +1,8 @@
create cstr1 ," A sample string"
create cstr2 ," another string"
create buf 256 allot
cstr1 count buf place
s" and " buf +place
cstr2 count buf +place
buf count type \ A sample string and another string

View file

@ -0,0 +1,85 @@
package main
import (
"bytes"
"fmt"
)
// Strings in Go allow arbitrary bytes. They are implemented basically as
// immutable byte slices and syntactic sugar. This program shows functions
// required by the task on byte slices, thus it mostly highlights what
// happens behind the syntactic sugar. The program does not attempt to
// reproduce the immutability property of strings, as that does not seem
// to be the intent of the task.
func main() {
// Task point: String creation and destruction.
// Strings are most often constructed from literals as in s := "binary"
// With byte slices,
b := []byte{'b', 'i', 'n', 'a', 'r', 'y'}
fmt.Println(b) // output shows numeric form of bytes.
// Go is garbage collected. There are no destruction operations.
// Task point: String assignment.
// t = s assigns strings. Since strings are immutable, it is irrelevant
// whether the string is copied or not.
// With byte slices, the same works,
var c []byte
c = b
fmt.Println(c)
// Task point: String comparison.
// operators <, <=, ==, >=, and > work directly on strings comparing them
// by lexicographic order.
// With byte slices, there are standard library functions, bytes.Equal
// and bytes.Compare.
fmt.Println(bytes.Equal(b, c)) // prints true
// Task point: String cloning and copying.
// The immutable property of Go strings makes cloning and copying
// meaningless for strings.
// With byte slices though, it is relevant. The assignment c = b shown
// above does a reference copy, leaving both c and b based on the same
// underlying data. To clone or copy the underlying data,
d := make([]byte, len(b)) // allocate new space
copy(d, b) // copy the data
// The data can be manipulated independently now:
d[1] = 'a'
d[4] = 'n'
fmt.Println(string(b)) // convert to string for readable output
fmt.Println(string(d))
// Task point: Check if a string is empty.
// Most typical for strings is s == "", but len(s) == 0 works too.
// For byte slices, "" does not work, len(b) == 0 is correct.
fmt.Println(len(b) == 0)
// Task point: Append a byte to a string.
// The language does not provide a way to do this directly with strings.
// Instead, the byte must be converted to a one-byte string first, as in,
// s += string('z')
// For byte slices, the language provides the append function,
z := append(b, 'z')
fmt.Printf("%s\n", z) // another way to get readable output
// Task point: Extract a substring from a string.
// Slicing syntax is the for both strings and slices.
sub := b[1:3]
fmt.Println(string(sub))
// Task point: Replace every occurrence of a byte (or a string)
// in a string with another string.
// Go supports this with similar library functions for strings and
// byte slices. Strings: t = strings.Replace(s, "n", "m", -1).
// The byte slice equivalent returns a modified copy, leaving the
// original byte slice untouched,
f := bytes.Replace(d, []byte{'n'}, []byte{'m'}, -1)
fmt.Printf("%s -> %s\n", d, f)
// Task point: Join strings.
// Using slicing syntax again, with strings,
// rem := s[:1] + s[3:] leaves rem == "bary".
// Only the concatenation of the parts is different with byte slices,
rem := append(append([]byte{}, b[:1]...), b[3:]...)
fmt.Println(string(rem))
}

View file

@ -0,0 +1,8 @@
{- Comparing two given strings and
returning a boolean result using a
simple conditional -}
strCompare :: String -> String -> Bool
strCompare x y =
if x == y
then True
else False

View file

@ -0,0 +1,8 @@
{- As strings are equivalent to lists
of characters in Haskell, test and
see if the given string is an empty list -}
strIsEmpty :: String -> Bool
strIsEmpty x =
if x == []
then True
else False

View file

@ -0,0 +1,8 @@
{- This is the most obvious way to
append strings, using the built-in
(++) concatenation operator
Note the same would work to join
any two strings (as 'variables' or
as typed strings -}
strAppend :: String -> String -> String
strAppend x y = x ++ y

View file

@ -0,0 +1,4 @@
{- Take the specified number of characters
from the given string -}
strExtract :: Int -> String -> String
strExtract x s = take x s

View file

@ -0,0 +1,4 @@
{- Take a certain substring, specified by
two integers, from the given string -}
strPull :: Int -> Int -> String -> String
strPull x y s = take (y-x+1) (drop x s)

View file

@ -0,0 +1,5 @@
{- Much thanks to brool.com for this nice
and elegant solution. Using an imported standard library
(Text.Regex), replace a given substring with another -}
strReplace :: String -> String -> String -> String
strReplace old new orig = subRegex (mkRegex old) orig new

View file

@ -0,0 +1,9 @@
import Text.Regex
{- The above import is needed only for the last function.
It is used there purely for readability and conciseness -}
{- Assigning a string to a 'variable'.
We're being explicit about it just for show.
Haskell would be able to figure out the type
of "world" -}
string = "world" :: String

View file

@ -0,0 +1,31 @@
foo = 'foo' -- Ducktyping foo to be string 'foo'
bar = 'bar'
assert (foo == "foo") -- Comparing string var to string literal
assert (foo ~= bar)
str = foo -- Copy foo contents to str
if #str == 0 then -- # operator returns string length
print 'str is empty'
end
str=str..string.char(50)-- Char concatenated with .. operator
substr = str:sub(1,3) -- Extract substring from index 1 to 3, inclusively
str = "string string string string"
-- This function will replace all occurances of 'replaced' in a string with 'replacement'
function replaceAll(str,replaced,replacement)
local function sub (a,b)
if b > a then
return str:sub(a,b)
end
return nil
end
a,b = str:find(replaced)
while a do
str = str:sub(1,a-1) .. replacement .. str:sub(b+1,#str)
a,b = str:find(replaced)
end
return str
end
str = replaceAll (str, 'ing', 'ong')
print (str)
str = foo .. bar -- Strings concatenate with .. operator

View file

@ -0,0 +1,6 @@
: (hd "rawfile")
00000000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ................
00000010 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F ................
00000020 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F !"#$%&'()*+,-./
00000030 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 0123456789:;<=>?
...

View file

@ -0,0 +1,5 @@
: (in '(dd "skip=32" "bs=1" "count=16" "if=rawfile")
(make
(while (rd 1)
(link @) ) ) )
-> (32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47)

View file

@ -0,0 +1,2 @@
: (pack (mapcar char (32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47)))
-> " !\"#$%&'()*+,-./"

View file

@ -0,0 +1,2 @@
: (out "rawfile"
(mapc wr (range 0 255)) )

View file

@ -0,0 +1,5 @@
items = ["Smith", "John", "417 Evergreen Av", "Chimichurri", "481-3172"]
joined = ",".join(items)
print joined
# output:
# Smith,John,417 Evergreen Av,Chimichurri,481-3172

View file

@ -0,0 +1,5 @@
line = "Smith,John,417 Evergreen Av,Chimichurri,481-3172"
fields = line.split(',')
print fields
# output:
# ['Smith', 'John', '417 Evergreen Av', 'Chimichurri', '481-3172']

View file

@ -0,0 +1,5 @@
s1 = b"A 'byte string' literal \n"
s2 = b'You may use any of \' or " as delimiter'
s3 = b"""This text
goes over several lines
up to the closing triple quote"""

View file

@ -0,0 +1,2 @@
x = b'abc'
x[0] # evaluates to 97

View file

@ -0,0 +1,3 @@
x = b'abc'
list(x) # evaluates to [97, 98, 99]
bytes([97, 98, 99]) # evaluates to b'abc'

View file

@ -0,0 +1,3 @@
s = "Hello "
t = "world!"
u = s + t # + concatenates

View file

@ -0,0 +1,4 @@
assert "Hello" == 'Hello'
assert '\t' == '\x09'
assert "one" < "two"
assert "two" >= "three"

View file

@ -0,0 +1,2 @@
if x=='': print "Empty string"
if not x: print "Empty string, provided you know x is a string"

View file

@ -0,0 +1,3 @@
txt = "Some text"
txt += '\x07'
# txt refers now to a new string having "Some text\x07"

View file

@ -0,0 +1,6 @@
txt = "Some more text"
assert txt[4] == " "
assert txt[0:4] == "Some"
assert txt[:4] == "Some" # you can omit the starting index if 0
assert txt[5:9] == "more"
assert txt[5:] == "more text" # omitting the second index means "to the end"

View file

@ -0,0 +1,3 @@
txt = "Some more text"
assert txt[-1] == "t"
assert txt[-4:] == "text"

View file

@ -0,0 +1,3 @@
v1 = "hello world"
v2 = v1.replace("l", "L")
print v2 # prints heLLo worLd

View file

@ -0,0 +1,3 @@
v1 = "hello"
v2 = "world"
msg = v1 + " " + v2

View file

@ -0,0 +1,5 @@
s1 = "A 'string' literal \n"
s2 = 'You may use any of \' or " as delimiter'
s3 = """This text
goes over several lines
up to the closing triple quote"""

View file

@ -0,0 +1,31 @@
/*REXX program shows ways to use and express binary strings. */
dingsta='11110101'b /*4 versions, bit str assignment.*/
dingsta="11110101"b /*same as above. */
dingsta='11110101'B /*same as above. */
dingsta='1111 0101'B /*same as above. */
dingst2=dingsta /*clone 1 str to another (copy). */
other='1001 0101 1111 0111'b /*another binary (bit) string. */
if dingsta=other then say 'they are equal' /*compare two strings.*/
if other=='' then say 'OTHER is empty.' /*see if it's empty. */
if length(other)==0 then say 'OTHER is empty.' /*another version. */
otherA=other || '$' /*append a dollar sign to OTHER. */
otherB=other'$' /*same as above, with less fuss. */
guts=substr(c2b(other),10,3) /*get the 10th through 12th bits.*/
/*see sub below. Some REXXes */
/*have C2B as a built-in function*/
new=changestr('A',other,"Z") /*change the letter A to Z. */
tt=changestr('~~',other,";") /*change 2 tildes to a semicolon.*/
joined=dignsta || dingst2 /*join 2 strs together (concat). */
exit /*stick a fork in it, we're done.*/
/*─────────────────────────────────C2B subroutine───────────────────────*/
c2b: return x2b(c2x(arg(1))) /*return the string as a binary string. */

View file

@ -0,0 +1,47 @@
#lang racket
;; Byte strings can be created either by a function (b1)
;; or as a literal string (b2). No operation is needed for
;; destruction due to garbage collection.
(define b1 (make-bytes 5 65)) ; b1 -> #"AAAAA"
(define b2 #"BBBBB") ; b2 -> #"BBBBB"
;; String assignment. Note that b2 cannot be
;; mutated since literal byte strings are immutable.
(bytes-set! b1 0 66) ; b1 -> #"BAAAA"
;; Comparison. Less than & greater than are
;; lexicographic comparison.
(bytes=? b1 b2) ; -> #f
(bytes<? b1 b2) ; -> #t
(bytes>? b1 b2) ; -> #f
;; Byte strings can be cloned by copying to a
;; new one or by overwriting an existing one.
(define b3 (bytes-copy b1)) ; b3 -> #"BAAAA"
(bytes-copy! b1 0 b2) ; b1 -> #"BBBBB"
;; Byte strings can be appended to one another. A
;; single byte is appended as a length 1 string.
(bytes-append b1 b2) ; -> #"BBBBBBBBBB"
(bytes-append b3 #"B") ; -> #"BAAAAB"
;; Substring
(subbytes b3 0) ; -> #"BAAAA"
(subbytes b3 0 2) ; -> #"BA"
;; Regular expressions can be used to do replacements
;; in a byte string (or ordinary strings)
(regexp-replace #"B" b1 #"A") ; -> #"ABBBB" (only the first one)
(regexp-replace* #"B" b1 #"A") ; -> #"AAAAA"
;; Joining strings
(bytes-join (list b2 b3) #" ") ; -> #"BBBBB BAAAA"

View file

@ -0,0 +1,45 @@
# string creation
x = "hello world"
# string destruction
x = nil
# string assignment with a null byte
x = "a\0b"
x.length # ==> 3
# string comparison
if x == "hello"
puts equal
else
puts "not equal"
end
y = 'bc'
if x < y
puts "#{x} is lexicographically less than #{y}"
end
# string cloning
xx = x.dup
x == xx # true, same length and content
x.equal?(xx) # false, different objects
# check if empty
if x.empty?
puts "is empty"
end
# append a byte
x << "\07"
# substring
xx = x[0..-2]
# replace bytes
y = "hello world".tr("l", "L")
# join strings
a = "hel"
b = "lo w"
c = "orld"
d = a + b + c

View file

@ -0,0 +1,36 @@
# string creation
set x "hello world"
# string destruction
unset x
# string assignment with a null byte
set x a\0b
string length $x ;# ==> 3
# string comparison
if {$x eq "hello"} {puts equal} else {puts "not equal"}
set y bc
if {$x < $y} {puts "$x is lexicographically less than $y"}
# string copying; cloning happens automatically behind the scenes
set xx $x
# check if empty
if {$x eq ""} {puts "is empty"}
if {[string length $x] == 0} {puts "is empty"}
# append a byte
append x \07
# substring
set xx [string range $x 0 end-1]
# replace bytes
set y [string map {l L} "hello world"]
# join strings
set a "hel"
set b "lo w"
set c "orld"
set d $a$b$c