Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

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

View file

@ -19,18 +19,18 @@ cdp(...)
r_last(r, v);
i = 0;
while ((c = character(s, i)) == character(v, i) && c) {
while ((c = s[i]) == v[i] && c) {
i += 1;
}
if (!c && character(v, i) == '/') {
if (!c && v[i] == '/') {
} else {
while (i && character(s, i - 1) != '/') {
while (i && s[i - 1] != '/') {
i -= 1;
}
}
if (1 < i && character(s, i - 1) == '/') {
if (1 < i && s[i - 1] == '/') {
i -= 1;
}

View file

@ -1,65 +1,59 @@
package main
import(
import (
"fmt"
"os"
"path"
"strings"
)
func CommonPrefix(sep string, paths ...string) (string) {
func CommonPrefix(sep byte, paths ...string) string {
// Handle special cases.
switch len(paths) {
case 0:
return ""
case 1:
return path.Clean(paths[0])
case 0:
return ""
case 1:
return path.Clean(paths[0])
}
// Note, we treat string as []byte, not []rune as is often
// done in Go. (And sep as byte, not rune). This is because
// most/all supported OS' treat paths as string of non-zero
// bytes. A filename may be displayed as a sequence of Unicode
// runes (typically encoded as UTF-8) but paths are
// not required to be valid UTF-8 or in any normalized form
// (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
// file names.
c := []byte(path.Clean(paths[0]))
// Ignore the first path since it's already in c.
for _, v := range(paths[1:]) {
// Clean up each path before testing it.
v = path.Clean(v)
// We add a trailing sep to handle the case where the
// common prefix directory is included in the path list
// (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
// path.Clean will have cleaned off trailing / separators with
// the exception of the root directory, "/" (in which case we
// make it "//", but this will get fixed up to "/" bellow).
c = append(c, sep)
// Get the length of the shorter slice.
shorter := len(v)
if len(v) > len(c) {
shorter = len(c)
// Ignore the first path since it's already in c
for _, v := range paths[1:] {
// Clean up each path before testing it
v = path.Clean(v) + string(sep)
// Find the first non-common byte and truncate c
if len(v) < len(c) {
c = c[:len(v)]
}
// Find the first non-common character and copy up to it into c.
for i := 0; i < shorter; i++ {
for i := 0; i < len(c); i++ {
if v[i] != c[i] {
c = c[0:i]
c = c[:i]
break
}
}
}
// Correct for problem caused by prepending the actual common path to the
// list of paths searched through.
for _, v := range(paths) {
if len(v) > len(c) {
if strings.HasPrefix(v, string(c)) {
if len(v) > len(c) + len(sep) {
if v[len(c):len(c)+len(sep)] == sep {
c = append(c, []byte(sep)...)
break
}
}
}
}
}
// Remove trailing non-seperator characters.
for i := len(c)-1; i >= 0; i-- {
if i + len(sep) > len(c) {
continue
}
if string(c[i:i+len(sep)]) == sep {
c = c[0:i]
// Remove trailing non-separator characters and the final separator
for i := len(c) - 1; i >= 0; i-- {
if c[i] == sep {
c = c[:i]
break
}
}
@ -68,10 +62,18 @@ func CommonPrefix(sep string, paths ...string) (string) {
}
func main() {
c := CommonPrefix("/",
c := CommonPrefix(os.PathSeparator,
//"/home/user1/tmp",
"/home/user1/tmp/coverage/test",
"/home/user1/tmp/covert/operator",
"/home/user1/tmp/coven/members",
"/home//user1/tmp/coventry",
"/home/user1/././tmp/covertly/foo",
"/home/bob/../user1/tmp/coved/bar",
)
fmt.Printf("%v\n", c)
if c == "" {
fmt.Println("No common path")
} else {
fmt.Println("Common path:", c)
}
}

View file

@ -0,0 +1,6 @@
sub common_prefix {
my $sep = shift;
my $paths = join "\0", map { $_.$sep } @_;
$paths =~ /^ ( [^\0]* ) $sep [^\0]* (?: \0 \1 $sep [^\0]* )* $/sx;
return $1;
}

View file

@ -0,0 +1,12 @@
use List::Util qw(first);
sub common_prefix {
my ($sep, @paths) = @_;
my %prefixes;
foreach (@paths) {
do { ++$prefixes{$_} } while s/$sep [^$sep]* $//g
}
return first { $prefixes{$_} == @paths } reverse sort keys %prefixes;
}

View file

@ -0,0 +1,4 @@
my @paths = qw(/home/user1/tmp/coverage/test
/home/user1/tmp/covert/operator
/home/user1/tmp/coven/members);
print common_prefix('/', @paths), "\n";

View file

@ -1,19 +0,0 @@
use List::Util qw(max reduce);
sub compath {
my ($sep, @paths, %hash) = @_;
# Tokenize and tally subpaths
foreach (@paths) {
my @tok = split $sep, substr($_,1);
++$hash{join $sep, @tok[0..$_]} for (0..$#tok); }
# Return max length subpath or null
my $max = max values %hash;
return '' unless $max == @paths;
my @res = grep {$hash{$_} == $max} keys %hash;
return $sep . reduce { length $a > length $b ? $a : $b } @res;
}
# Test and display
my @paths = qw(/home/user1/tmp/coverage/test
/home/user1/tmp/covert/operator
/home/user1/tmp/coven/members);
print compath('/', @paths), "\n";

View file

@ -3,4 +3,4 @@ require 'abbrev'
dirs = %w( /home/user1/tmp/coverage/test /home/user1/tmp/covert/operator /home/user1/tmp/coven/members )
common_prefix = dirs.abbrev.keys.min_by {|key| key.length}.chop # => "/home/user1/tmp/cove"
common_directory = common_prefix.sub(%r{/[^/]*$}, '') # => "/home/user1/tmp"
common_directory = common_prefix.sub(%r{/[^/]*$}, '') # => "/home/user1/tmp"

View file

@ -1,4 +1,5 @@
separator = '/'
paths = dirs.collect {|dir| dir.split(separator)}
uncommon_idx = paths.transpose.each_with_index.find {|dirnames, idx| dirnames.uniq.length > 1}.last
common_directory = paths[0][0 ... uncommon_idx].join(separator) # => "/home/user1/tmp"
uncommon_idx = paths[0].zip(*paths[1..-1]).index {|dirnames| dirnames.uniq.length > 1}
uncommon_idx = paths[0].length unless uncommon_idx # if uncommon_idx==nil
common_directory = paths[0][0...uncommon_idx].join(separator) # => "/home/user1/tmp"

View file

@ -0,0 +1,17 @@
object FindCommonDirectoryPath extends App {
def commonPath(paths: List[String]): String = {
def common(a: List[String], b: List[String]): List[String] = (a, b) match {
case (a :: as, b :: bs) if a equals b => a :: common(as, bs)
case _ => Nil
}
if (paths.length < 2) paths.headOption.getOrElse("")
else paths.map(_.split("/").toList).reduceLeft(common).mkString("/")
}
val test = List(
"/home/user1/tmp/coverage/test",
"/home/user1/tmp/covert/operator",
"/home/user1/tmp/coven/members"
)
println(commonPath(test))
}

View file

@ -0,0 +1,50 @@
object FindCommonDirectoryPathRelative extends App {
def commonPath(paths: List[String]): String = {
val SEP = "/"
val BOUNDARY_REGEX = s"(?=[$SEP])(?<=[^$SEP])|(?=[^$SEP])(?<=[$SEP])"
def common(a: List[String], b: List[String]): List[String] = (a, b) match {
case (a :: as, b :: bs) if a equals b => a :: common(as, bs)
case _ => Nil
}
if (paths.length < 2) paths.headOption.getOrElse("")
else paths.map(_.split(BOUNDARY_REGEX).toList).reduceLeft(common).mkString
}
val test = List(
"/home/user1/tmp/coverage/test",
"/home/user1/tmp/covert/operator",
"/home/user1/tmp/coven/members"
)
println(commonPath(test).replaceAll("/$", ""))
// test cases
assert(commonPath(test.take(1)) == test.head)
assert(commonPath(Nil) == "")
assert(commonPath(List("")) == "")
assert(commonPath(List("/")) == "/")
assert(commonPath(List("/", "")) == "")
assert(commonPath(List("/", "/a")) == "/")
assert(commonPath(List("/a", "/b")) == "/")
assert(commonPath(List("/a", "/a")) == "/a")
assert(commonPath(List("/a/a", "/b")) == "/")
assert(commonPath(List("/a/a", "/b")) == "/")
assert(commonPath(List("/a/a", "/a")) == "/a")
assert(commonPath(List("/a/a", "/a/b")) == "/a/")
assert(commonPath(List("/a/b", "/a/b")) == "/a/b")
assert(commonPath(List("a", "/a")) == "")
assert(commonPath(List("a/a", "/a")) == "")
assert(commonPath(List("a/a", "/b")) == "")
assert(commonPath(List("a", "a")) == "a")
assert(commonPath(List("a/a", "b")) == "")
assert(commonPath(List("a/a", "b")) == "")
assert(commonPath(List("a/a", "a")) == "a")
assert(commonPath(List("a/a", "a/b")) == "a/")
assert(commonPath(List("a/b", "a/b")) == "a/b")
assert(commonPath(List("/a/", "/b/")) == "/")
assert(commonPath(List("/a/", "/a/")) == "/a/")
assert(commonPath(List("/a/a/", "/b/")) == "/")
assert(commonPath(List("/a/a/", "/b/")) == "/")
assert(commonPath(List("/a/a/", "/a/")) == "/a/")
assert(commonPath(List("/a/a/", "/a/b/")) == "/a/")
assert(commonPath(List("/a/b/", "/a/b/")) == "/a/b/")
}