A-M baby
This commit is contained in:
parent
764da6cbbb
commit
db842d013d
19005 changed files with 197040 additions and 7 deletions
9
Task/Find-common-directory-path/0DESCRIPTION
Normal file
9
Task/Find-common-directory-path/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
Create a routine that, given a set of strings representing directory paths and a single character directory separator, will return a string representing that part of the directory tree that is common to all the directories.
|
||||
|
||||
Test your routine using the forward slash '/' character as the directory separator and the following three strings as input paths:
|
||||
'/home/user1/tmp/coverage/test'
|
||||
'/home/user1/tmp/covert/operator'
|
||||
'/home/user1/tmp/coven/members'
|
||||
|
||||
Note: The resultant path should be the valid directory <code>'/home/user1/tmp'</code> and not the longest common string <code>'/home/user1/tmp/cove'</code>.<br>
|
||||
If your language has a routine that performs this function (even if it does not have a changeable separator character), then mention it as part of the task.
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
# Utilities code #
|
||||
|
||||
CHAR dir sep = "/"; # Assume POSIX #
|
||||
|
||||
PROC dir name = (STRING dir)STRING: (
|
||||
STRING out;
|
||||
FOR pos FROM UPB dir BY -1 TO LWB dir DO
|
||||
IF dir[pos] = dir sep THEN
|
||||
out := dir[:pos-1];
|
||||
GO TO out exit
|
||||
FI
|
||||
OD;
|
||||
# else: # out:="";
|
||||
out exit: out
|
||||
);
|
||||
|
||||
PROC shortest = ([]STRING string list)STRING: (
|
||||
INT min := max int;
|
||||
INT min key := LWB string list - 1;
|
||||
FOR key FROM LWB string list TO UPB string list DO
|
||||
IF UPB string list[key][@1] < min THEN
|
||||
min := UPB string list[key][@1];
|
||||
min key := key
|
||||
FI
|
||||
OD;
|
||||
string list[min key]
|
||||
);
|
||||
|
||||
# Actual code #
|
||||
|
||||
PROC common prefix = ([]STRING strings)STRING: (
|
||||
IF LWB strings EQ UPB strings THEN
|
||||
# exit: # strings[LWB strings]
|
||||
ELSE
|
||||
STRING prefix := shortest(strings);
|
||||
FOR pos FROM LWB prefix TO UPB prefix DO
|
||||
CHAR first = prefix[pos];
|
||||
FOR key FROM LWB strings+1 TO UPB strings DO
|
||||
IF strings[key][@1][pos] NE first THEN
|
||||
prefix := prefix[:pos-1];
|
||||
GO TO prefix exit
|
||||
FI
|
||||
OD
|
||||
OD;
|
||||
prefix exit: prefix
|
||||
FI
|
||||
);
|
||||
|
||||
# Test code #
|
||||
|
||||
test:(
|
||||
[]STRING dir list = (
|
||||
"/home/user1/tmp/coverage/test",
|
||||
"/home/user1/tmp/covert/operator",
|
||||
"/home/user1/tmp/coven/members"
|
||||
);
|
||||
print((dir name(common prefix(dir list)), new line))
|
||||
)
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
# Finds the longest common directory of paths[1], paths[2], ...,
|
||||
# paths[count], where sep is a single-character directory separator.
|
||||
function common_dir(paths, count, sep, b, c, f, i, j, p) {
|
||||
if (count < 1)
|
||||
return ""
|
||||
|
||||
p = "" # Longest common prefix
|
||||
f = 0 # Final index before last sep
|
||||
|
||||
# Loop for c = each character of paths[1].
|
||||
for (i = 1; i <= length(paths[1]); i++) {
|
||||
c = substr(paths[1], i, 1)
|
||||
|
||||
# If c is not the same in paths[2], ..., paths[count]
|
||||
# then break both loops.
|
||||
b = 0
|
||||
for (j = 2; j <= count; j++) {
|
||||
if (c != substr(paths[j], i, 1)) {
|
||||
b = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
if (b)
|
||||
break
|
||||
|
||||
# Append c to prefix. Update f.
|
||||
p = p c
|
||||
if (c == sep)
|
||||
f = i - 1
|
||||
}
|
||||
|
||||
# Return only f characters of prefix.
|
||||
return substr(p, 1, f)
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
a[1] = "/home/user1/tmp/coverage/test"
|
||||
a[2] = "/home/user1/tmp/covert/operator"
|
||||
a[3] = "/home/user1/tmp/coven/members"
|
||||
print common_dir(a, 3, "/")
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
|
||||
procedure Test_Common_Path is
|
||||
function "rem" (A, B : String) return String is
|
||||
Slash : Integer := A'First; -- At the last slash seen in A
|
||||
At_A : Integer := A'first;
|
||||
At_B : Integer := B'first;
|
||||
begin
|
||||
loop
|
||||
if At_A > A'Last then
|
||||
if At_B > B'Last or else B (At_B) = '/' then
|
||||
return A;
|
||||
else
|
||||
return A (A'First..Slash - 1);
|
||||
end if;
|
||||
elsif At_B > B'Last then
|
||||
if A (At_A) = '/' then -- A cannot be shorter than B here
|
||||
return B;
|
||||
else
|
||||
return A (A'First..Slash - 1);
|
||||
end if;
|
||||
elsif A (At_A) /= B (At_B) then
|
||||
return A (A'First..Slash - 1);
|
||||
elsif A (At_A) = '/' then
|
||||
Slash := At_A;
|
||||
end if;
|
||||
At_A := At_A + 1;
|
||||
At_B := At_B + 1;
|
||||
end loop;
|
||||
end "rem";
|
||||
begin
|
||||
Put_Line
|
||||
( "/home/user1/tmp/coverage/test" rem
|
||||
"/home/user1/tmp/covert/operator" rem
|
||||
"/home/user1/tmp/coven/members"
|
||||
);
|
||||
end Test_Common_Path;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
Dir1 := "/home/user1/tmp/coverage/test"
|
||||
Dir2 := "/home/user1/tmp/covert/operator"
|
||||
Dir3 := "/home/user1/tmp/coven/members"
|
||||
|
||||
StringSplit, Dir1_, Dir1, /
|
||||
StringSplit, Dir2_, Dir2, /
|
||||
StringSplit, Dir3_, Dir3, /
|
||||
|
||||
Loop
|
||||
If (Dir1_%A_Index% = Dir2_%A_Index%)
|
||||
And (Dir1_%A_Index% = Dir3_%A_Index%)
|
||||
Result .= (A_Index=1 ? "" : "/") Dir1_%A_Index%
|
||||
Else Break
|
||||
|
||||
MsgBox, % Result
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
DECLARE FUNCTION commonPath$ (paths() AS STRING, pathSep AS STRING)
|
||||
|
||||
DATA "/home/user2", "/home/user1/tmp/covert/operator", "/home/user1/tmp/coven/members"
|
||||
|
||||
DIM x(0 TO 2) AS STRING, n AS INTEGER
|
||||
FOR n = 0 TO 2
|
||||
READ x(n)
|
||||
NEXT
|
||||
|
||||
PRINT "Common path is '"; commonPath$(x(), "/"); "'"
|
||||
|
||||
FUNCTION commonPath$ (paths() AS STRING, pathSep AS STRING)
|
||||
DIM tmpint1 AS INTEGER, tmpint2 AS INTEGER, tmpstr1 AS STRING, tmpstr2 AS STRING
|
||||
DIM L0 AS INTEGER, L1 AS INTEGER, lowerbound AS INTEGER, upperbound AS INTEGER
|
||||
lowerbound = LBOUND(paths): upperbound = UBOUND(paths)
|
||||
|
||||
IF (lowerbound) = upperbound THEN 'Some quick error checking...
|
||||
commonPath$ = paths(lowerbound)
|
||||
ELSEIF lowerbound > upperbound THEN 'How in the...?
|
||||
commonPath$ = ""
|
||||
ELSE
|
||||
tmpstr1 = paths(lowerbound)
|
||||
|
||||
FOR L0 = (lowerbound + 1) TO upperbound 'Find common strings.
|
||||
tmpstr2 = paths(L0)
|
||||
tmpint1 = LEN(tmpstr1)
|
||||
tmpint2 = LEN(tmpstr2)
|
||||
IF tmpint1 > tmpint2 THEN tmpint1 = tmpint2
|
||||
FOR L1 = 1 TO tmpint1
|
||||
IF MID$(tmpstr1, L1, 1) <> MID$(tmpstr2, L1, 1) THEN
|
||||
tmpint1 = L1 - 1
|
||||
EXIT FOR
|
||||
END IF
|
||||
NEXT
|
||||
tmpstr1 = LEFT$(tmpstr1, tmpint1)
|
||||
NEXT
|
||||
|
||||
IF RIGHT$(tmpstr1, 1) <> pathSep THEN
|
||||
FOR L1 = tmpint1 TO 2 STEP -1
|
||||
IF (pathSep) = MID$(tmpstr1, L1, 1) THEN
|
||||
tmpstr1 = LEFT$(tmpstr1, L1 - 1)
|
||||
EXIT FOR
|
||||
END IF
|
||||
NEXT
|
||||
IF LEN(tmpstr1) = tmpint1 THEN tmpstr1 = ""
|
||||
ELSEIF tmpint1 > 1 THEN
|
||||
tmpstr1 = LEFT$(tmpstr1, tmpint1 - 1)
|
||||
END IF
|
||||
|
||||
commonPath$ = tmpstr1
|
||||
END IF
|
||||
END FUNCTION
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
DIM path$(3)
|
||||
|
||||
path$(1) = "/home/user1/tmp/coverage/test"
|
||||
path$(2) = "/home/user1/tmp/covert/operator"
|
||||
path$(3) = "/home/user1/tmp/coven/members"
|
||||
|
||||
PRINT FNcommonpath(path$(), "/")
|
||||
END
|
||||
|
||||
DEF FNcommonpath(p$(), s$)
|
||||
LOCAL I%, J%, O%
|
||||
REPEAT
|
||||
O% = I%
|
||||
I% = INSTR(p$(1), s$, I%+1)
|
||||
FOR J% = 2 TO DIM(p$(), 1)
|
||||
IF LEFT$(p$(1), I%) <> LEFT$(p$(J%), I%) EXIT REPEAT
|
||||
NEXT J%
|
||||
UNTIL I% = 0
|
||||
= LEFT$(p$(1), O%-1)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
std::string longestPath( const std::vector<std::string> & , char ) ;
|
||||
|
||||
int main( ) {
|
||||
std::string dirs[ ] = {
|
||||
"/home/user1/tmp/coverage/test" ,
|
||||
"/home/user1/tmp/covert/operator" ,
|
||||
"/home/user1/tmp/coven/members" } ;
|
||||
std::vector<std::string> myDirs ( dirs , dirs + 3 ) ;
|
||||
std::cout << "The longest common path of the given directories is "
|
||||
<< longestPath( myDirs , '/' ) << "!\n" ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
std::string longestPath( const std::vector<std::string> & dirs , char separator ) {
|
||||
std::vector<std::string>::const_iterator vsi = dirs.begin( ) ;
|
||||
int maxCharactersCommon = vsi->length( ) ;
|
||||
std::string compareString = *vsi ;
|
||||
for ( vsi = dirs.begin( ) + 1 ; vsi != dirs.end( ) ; vsi++ ) {
|
||||
std::pair<std::string::const_iterator , std::string::const_iterator> p =
|
||||
std::mismatch( compareString.begin( ) , compareString.end( ) , vsi->begin( ) ) ;
|
||||
if (( p.first - compareString.begin( ) ) < maxCharactersCommon )
|
||||
maxCharactersCommon = p.first - compareString.begin( ) ;
|
||||
}
|
||||
std::string::size_type found = compareString.rfind( separator , maxCharactersCommon ) ;
|
||||
return compareString.substr( 0 , found ) ;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int common_len(const char *const *names, int n, char sep)
|
||||
{
|
||||
int i, pos;
|
||||
for (pos = 0; ; pos++) {
|
||||
for (i = 0; i < n; i++) {
|
||||
if (names[i][pos] != '\0' &&
|
||||
names[i][pos] == names[0][pos])
|
||||
continue;
|
||||
|
||||
/* backtrack */
|
||||
while (pos > 0 && names[0][--pos] != sep);
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const char *names[] = {
|
||||
"/home/user1/tmp/coverage/test",
|
||||
"/home/user1/tmp/covert/operator",
|
||||
"/home/user1/tmp/coven/members",
|
||||
};
|
||||
int len = common_len(names, sizeof(names) / sizeof(const char*), '/');
|
||||
|
||||
if (!len) printf("No common path\n");
|
||||
else printf("Common path: %.*s\n", len, names[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
Common path: /home/user1/tmp
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
(use '[clojure.string :only [join,split]])
|
||||
|
||||
(defn common-prefix [sep paths]
|
||||
(let [parts-per-path (map #(split % (re-pattern sep)) paths)
|
||||
parts-per-position (apply map vector parts-per-path)]
|
||||
(join sep
|
||||
(for [parts parts-per-position :while (apply = parts)]
|
||||
(first parts)))))
|
||||
|
||||
(println
|
||||
(common-prefix "/"
|
||||
["/home/user1/tmp/coverage/test"
|
||||
"/home/user1/tmp/covert/operator"
|
||||
"/home/user1/tmp/coven/members"]))
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import std.stdio, std.string, std.algorithm, std.path, std.array;
|
||||
|
||||
string commonDirPath(in string[] paths, in string sep = "/")
|
||||
/*pure nothrow*/ {
|
||||
if (paths.empty)
|
||||
return null;
|
||||
return paths.map!(p => p.split(sep)).reduce!commonPrefix.join(sep);
|
||||
}
|
||||
|
||||
void main() {
|
||||
auto paths = ["/home/user1/tmp/coverage/test",
|
||||
"/home/user1/tmp/covert/operator",
|
||||
"/home/user1/tmp/coven/members"];
|
||||
writeln(`The common path is: "`, paths.commonDirPath, '"');
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
: take-shorter ( seq1 seq2 -- shorter )
|
||||
[ shorter? ] 2keep ? ;
|
||||
|
||||
: common-head ( seq1 seq2 -- head )
|
||||
2dup mismatch [ nip head ] [ take-shorter ] if* ;
|
||||
|
||||
: common-prefix-1 ( file1 file2 separator -- prefix )
|
||||
[ common-head ] dip '[ _ = not ] trim-tail ;
|
||||
|
||||
: common-prefix ( seq separator -- prefix )
|
||||
[ ] swap '[ _ common-prefix-1 ] map-reduce ;
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
10 REM All GOTO statements can be replaced with EXIT FOR in newer BASICs.
|
||||
|
||||
110 X$ = "/home/user1/tmp/coverage/test"
|
||||
120 Y$ = "/home/user1/tmp/covert/operator"
|
||||
130 Z$ = "/home/user1/tmp/coven/members"
|
||||
|
||||
150 A = LEN(X$)
|
||||
160 IF A > LEN(Y$) THEN A = LEN(Y$)
|
||||
170 IF A > LEN(Z$) THEN A = LEN(Z$)
|
||||
180 FOR L0 = 1 TO A
|
||||
190 IF MID$(X$, L0, 1) <> MID$(Y$, L0, 1) THEN GOTO 210
|
||||
200 NEXT
|
||||
210 A = L0 - 1
|
||||
|
||||
230 FOR L0 = 1 TO A
|
||||
240 IF MID$(X$, L0, 1) <> MID$(Z$, L0, 1) THEN GOTO 260
|
||||
250 NEXT
|
||||
260 A = L0 - 1
|
||||
|
||||
280 IF MID$(X$, L0, 1) <> "/" THEN
|
||||
290 FOR L0 = A TO 1 STEP -1
|
||||
300 IF "/" = MID$(X$, L0, 1) THEN GOTO 340
|
||||
310 NEXT
|
||||
320 END IF
|
||||
|
||||
340 REM Task description says no trailing slash, so...
|
||||
350 A = L0 - 1
|
||||
360 P$ = LEFT$(X$, A)
|
||||
370 PRINT "Common path is '"; P$; "'"
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package main
|
||||
|
||||
import(
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func CommonPrefix(sep string, paths ...string) (string) {
|
||||
// Handle special cases.
|
||||
switch len(paths) {
|
||||
case 0:
|
||||
return ""
|
||||
case 1:
|
||||
return path.Clean(paths[0])
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
// Get the length of the shorter slice.
|
||||
shorter := len(v)
|
||||
if len(v) > len(c) {
|
||||
shorter = len(c)
|
||||
}
|
||||
|
||||
// Find the first non-common character and copy up to it into c.
|
||||
for i := 0; i < shorter; i++ {
|
||||
if v[i] != c[i] {
|
||||
c = c[0: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]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return string(c)
|
||||
}
|
||||
|
||||
func main() {
|
||||
c := CommonPrefix("/",
|
||||
"/home/user1/tmp/coverage/test",
|
||||
"/home/user1/tmp/covert/operator",
|
||||
"/home/user1/tmp/coven/members",
|
||||
)
|
||||
fmt.Printf("%v\n", c)
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
def commonPath = { delim, Object[] paths ->
|
||||
def pathParts = paths.collect { it.split(delim) }
|
||||
pathParts.transpose().inject([match:true, commonParts:[]]) { aggregator, part ->
|
||||
aggregator.match = aggregator.match && part.every { it == part [0] }
|
||||
if (aggregator.match) { aggregator.commonParts << part[0] }
|
||||
aggregator
|
||||
}.commonParts.join(delim)
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
println commonPath('/',
|
||||
'/home/user1/tmp/coverage/test',
|
||||
'/home/user1/tmp/covert/operator',
|
||||
'/home/user1/tmp/coven/members')
|
||||
|
||||
println commonPath('/',
|
||||
'/home/user1/tmp/coverage/test',
|
||||
'/home/user1/tmp/covert/test',
|
||||
'/home/user1/tmp/coven/test',
|
||||
'/home/user1/tmp/covers/test')
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import Data.List
|
||||
|
||||
-- Return the common prefix of two lists.
|
||||
commonPrefix2 (x:xs) (y:ys) | x == y = x : commonPrefix2 xs ys
|
||||
commonPrefix2 _ _ = []
|
||||
|
||||
-- Return the common prefix of zero or more lists.
|
||||
commonPrefix (xs:xss) = foldr commonPrefix2 xs xss
|
||||
commonPrefix _ = []
|
||||
|
||||
-- Split a string into path components.
|
||||
splitPath = groupBy (\_ c -> c /= '/')
|
||||
|
||||
-- Return the common prefix of zero or more paths.
|
||||
-- Note that '/' by itself is not considered a path component,
|
||||
-- so "/" and "/foo" are treated as having nothing in common.
|
||||
commonDirPath = concat . commonPrefix . map splitPath
|
||||
|
||||
main = putStrLn $ commonDirPath [
|
||||
"/home/user1/tmp/coverage/test",
|
||||
"/home/user1/tmp/covert/operator",
|
||||
"/home/user1/tmp/coven/members"
|
||||
]
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
CHARACTER a='/home/user1/tmp/coverage/test', b='/home/user1/tmp/covert/operator', c='/home/user1/tmp/coven/members'
|
||||
|
||||
minLength = MIN( LEN(a), LEN(b), LEN(c) )
|
||||
lastSlash = 0
|
||||
|
||||
DO i = 1, minLength
|
||||
IF( (a(i) == b(i)) * (b(i) == c(i)) ) THEN
|
||||
IF(a(i) == "/") lastSlash = i
|
||||
ELSEIF( lastSlash ) THEN
|
||||
WRITE(Messagebox) "Common Directory = ", a(1:lastSlash-1)
|
||||
ELSE
|
||||
WRITE(Messagebox, Name) "No common directory for", a, b, c
|
||||
ENDIF
|
||||
ENDDO
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
procedure main()
|
||||
write(lcdsubstr(["/home/user1/tmp/coverage/test","/home/user1/tmp/covert/operator","/home/user1/tmp/coven/members"]))
|
||||
end
|
||||
|
||||
procedure lcdsubstr(sL,d) #: return the longest common sub-string of strings in the list sL delimited by d
|
||||
local ss
|
||||
|
||||
/d := "/"
|
||||
reverse(sL[1]) ? {
|
||||
if tab(find(d)+*d) || allmatch(ss := reverse(tab(0)),sL) then
|
||||
return ss
|
||||
}
|
||||
end
|
||||
|
||||
procedure allmatch(s,L) #: retrun s if it matches all strings in L
|
||||
local x
|
||||
every x := !L do
|
||||
if not match(s,x) then fail
|
||||
return s
|
||||
end
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
parseDirs =: = <;.2 ]
|
||||
getCommonPrefix =: {. ;@{.~ 0 i.~ *./@(="1 {.)
|
||||
|
||||
getCommonDirPath=: [: getCommonPrefix parseDirs&>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
paths=: '/home/user1/tmp/coverage/test';'/home/user1/tmp/covert/operator';'/home/user1/tmp/coven/members'
|
||||
getCommonPrefix >paths
|
||||
/home/user1/tmp/cove
|
||||
'/' getCommonDirPath paths
|
||||
/home/user1/tmp/
|
||||
|
|
@ -0,0 +1 @@
|
|||
parseDirs =: (PATHSEP_j_&= <;.2 ])@jhostpath
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
public class CommonPath {
|
||||
public static String commonPath(String... paths){
|
||||
String commonPath = "";
|
||||
String[][] folders = new String[paths.length][];
|
||||
for(int i = 0; i < paths.length; i++){
|
||||
folders[i] = paths[i].split("/"); //split on file separator
|
||||
}
|
||||
for(int j = 0; j < folders[0].length; j++){
|
||||
String thisFolder = folders[0][j]; //grab the next folder name in the first path
|
||||
boolean allMatched = true; //assume all have matched in case there are no more paths
|
||||
for(int i = 1; i < folders.length && allMatched; i++){ //look at the other paths
|
||||
if(folders[i].length < j){ //if there is no folder here
|
||||
allMatched = false; //no match
|
||||
break; //stop looking because we've gone as far as we can
|
||||
}
|
||||
//otherwise
|
||||
allMatched &= folders[i][j].equals(thisFolder); //check if it matched
|
||||
}
|
||||
if(allMatched){ //if they all matched this folder name
|
||||
commonPath += thisFolder + "/"; //add it to the answer
|
||||
}else{//otherwise
|
||||
break;//stop looking
|
||||
}
|
||||
}
|
||||
return commonPath;
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
String[] paths = { "/home/user1/tmp/coverage/test",
|
||||
"/home/user1/tmp/covert/operator",
|
||||
"/home/user1/tmp/coven/members"};
|
||||
System.out.println(commonPath(paths));
|
||||
|
||||
String[] paths2 = { "/hame/user1/tmp/coverage/test",
|
||||
"/home/user1/tmp/covert/operator",
|
||||
"/home/user1/tmp/coven/members"};
|
||||
System.out.println(commonPath(paths2));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
path$(1) = "/home/user1/tmp/coverage/test"
|
||||
path$(2) = "/home/user1/tmp/covert/operator"
|
||||
path$(3) = "/home/user1/tmp/coven/members"
|
||||
|
||||
|
||||
print samepath$(3,"/")
|
||||
end
|
||||
|
||||
function samepath$(paths,sep$)
|
||||
d = 1 'directory depth
|
||||
n = 2 'path$(number)
|
||||
while 1
|
||||
if word$(path$(1),d,sep$) <> word$(path$(n),d,sep$) or word$(path$(1),d,sep$) = "" then exit while
|
||||
n = n + 1
|
||||
if n > paths then
|
||||
if right$(samepath$,1) <> sep$ and d<>1 then
|
||||
samepath$ = samepath$ + sep$ + word$(path$(1),d,sep$)
|
||||
else
|
||||
samepath$ = samepath$ + word$(path$(1),d,sep$)
|
||||
end if
|
||||
n = 2
|
||||
d = d + 1
|
||||
end if
|
||||
wend
|
||||
end function
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
FCD
|
||||
NEW D,SEP,EQ,LONG,DONE,I,J,K,RETURN
|
||||
SET D(1)="/home/user1/tmp/coverage/test"
|
||||
SET D(2)="/home/user1/tmp/covert/operator"
|
||||
SET D(3)="/home/user1/tmp/coven/members"
|
||||
SET SEP="/"
|
||||
SET LONG=D(1)
|
||||
SET DONE=0
|
||||
FOR I=1:1:$LENGTH(LONG,SEP) QUIT:DONE SET EQ(I)=1 FOR J=2:1:3 SET EQ(I)=($PIECE(D(J),SEP,I)=$PIECE(LONG,SEP,I))&EQ(I) SET DONE='EQ(I) QUIT:'EQ(I)
|
||||
SET RETURN=""
|
||||
FOR K=1:1:I-1 Q:'EQ(K) SET:EQ(K) $PIECE(RETURN,SEP,K)=$PIECE(LONG,SEP,K)
|
||||
WRITE !,"For the paths:" FOR I=1:1:3 WRITE !,D(I)
|
||||
WRITE !,"The longest common directory is: ",RETURN
|
||||
KILL D,SEP,EQ,LONG,DONE,I,J,K,RETURN
|
||||
QUIT
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
FindCommonDirectory[x_] := If[StringTake[#, -1] != "/", StringTake[#, Max[StringPosition[#, "/"]]], #] &
|
||||
[Fold[LongestCommonSubsequence, First[x] , Rest[x]]]
|
||||
|
||||
FindCommonDirectory[{"/home/user1/tmp/coverage/test", "/home/user1/tmp/covert/operator", "/home/user1/tmp/coven/members"}]
|
||||
->"/home/user1/tmp/"
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
scommon(a, b) := block([n: min(slength(a), slength(b))],
|
||||
substring(a, 1, catch(for i thru n do (
|
||||
if not cequal(charat(a, i), charat(b, i)) then throw(i)), n + 1)))$
|
||||
|
||||
commonpath(u, [l]) := block([s: lreduce(scommon, u), c, n],
|
||||
n: sposition(if length(l) = 0 then "/" else l[1], sreverse(s)),
|
||||
if integerp(n) then substring(s, 1, slength(s) - n) else ""
|
||||
)$
|
||||
|
||||
commonpath(["c:/files/banister.jpg", "c:/files/bank.xls", "c:/files/banana-recipes.txt"]);
|
||||
"c:/files"
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This works with dirs and files in any number of combinations.
|
||||
*/
|
||||
|
||||
function _commonPath($dirList)
|
||||
{
|
||||
$arr = array();
|
||||
foreach($dirList as $i => $path)
|
||||
{
|
||||
$dirList[$i] = explode('/', $path);
|
||||
unset($dirList[$i][0]);
|
||||
|
||||
$arr[$i] = count($dirList[$i]);
|
||||
}
|
||||
|
||||
$min = min($arr);
|
||||
|
||||
for($i = 0; $i < count($dirList); $i++)
|
||||
{
|
||||
while(count($dirList[$i]) > $min)
|
||||
{
|
||||
array_pop($dirList[$i]);
|
||||
}
|
||||
|
||||
$dirList[$i] = '/' . implode('/' , $dirList[$i]);
|
||||
}
|
||||
|
||||
$dirList = array_unique($dirList);
|
||||
while(count($dirList) !== 1)
|
||||
{
|
||||
$dirList = array_map('dirname', $dirList);
|
||||
$dirList = array_unique($dirList);
|
||||
}
|
||||
reset($dirList);
|
||||
|
||||
return current($dirList);
|
||||
}
|
||||
|
||||
/* TEST */
|
||||
|
||||
$dirs = array(
|
||||
'/home/user1/tmp/coverage/test',
|
||||
'/home/user1/tmp/covert/operator',
|
||||
'/home/user1/tmp/coven/members',
|
||||
);
|
||||
|
||||
|
||||
if('/home/user1/tmp' !== common_path($dirs))
|
||||
{
|
||||
echo 'test fail';
|
||||
} else {
|
||||
echo 'test success';
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
/* A more compact string-only version, which I assume would be much faster */
|
||||
/* If you want the trailing /, return $common; */
|
||||
|
||||
function getCommonPath($paths) {
|
||||
$lastOffset = 1;
|
||||
$common = '/';
|
||||
while (($index = strpos($paths[0], '/', $lastOffset)) !== FALSE) {
|
||||
$dirLen = $index - $lastOffset + 1; // include /
|
||||
$dir = substr($paths[0], $lastOffset, $dirLen);
|
||||
foreach ($paths as $path) {
|
||||
if (substr($path, $lastOffset, $dirLen) != $dir)
|
||||
return $common;
|
||||
}
|
||||
$common .= $dir;
|
||||
$lastOffset = $index + 1;
|
||||
}
|
||||
return substr($common, 0, -1);
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
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";
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
(de commonPath (Lst Chr)
|
||||
(glue Chr
|
||||
(make
|
||||
(apply find
|
||||
(mapcar '((L) (split (chop L) Chr)) Lst)
|
||||
'(@ (or (pass <>) (nil (link (next))))) ) ) ) )
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
>>> import os
|
||||
>>> os.path.commonprefix(['/home/user1/tmp/coverage/test',
|
||||
'/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members'])
|
||||
'/home/user1/tmp/cove'
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
>>> def commonprefix(*args, sep='/'):
|
||||
return os.path.commonprefix(*args).rpartition(sep)[0]
|
||||
|
||||
>>> commonprefix(['/home/user1/tmp/coverage/test',
|
||||
'/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members'])
|
||||
'/home/user1/tmp'
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
>>> from itertools import takewhile
|
||||
>>> def allnamesequal(name):
|
||||
return all(n==name[0] for n in name[1:])
|
||||
|
||||
>>> def commonprefix(paths, sep='/'):
|
||||
bydirectorylevels = zip(*[p.split(sep) for p in paths])
|
||||
return sep.join(x[0] for x in takewhile(allnamesequal, bydirectorylevels))
|
||||
|
||||
>>> commonprefix(['/home/user1/tmp/coverage/test',
|
||||
'/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members'])
|
||||
'/home/user1/tmp'
|
||||
>>> # And also
|
||||
>>> commonprefix(['/home/user1/tmp', '/home/user1/tmp/coverage/test',
|
||||
'/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members'])
|
||||
'/home/user1/tmp'
|
||||
>>>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
get_common_dir <- function(paths, delim = "/")
|
||||
{
|
||||
path_chunks <- strsplit(paths, delim)
|
||||
|
||||
i <- 1
|
||||
repeat({
|
||||
current_chunk <- sapply(path_chunks, function(x) x[i])
|
||||
if(any(current_chunk != current_chunk[1])) break
|
||||
i <- i + 1
|
||||
})
|
||||
paste(path_chunks[[1]][seq_len(i - 1)], collapse = delim)
|
||||
|
||||
}
|
||||
|
||||
# Example Usage:
|
||||
paths <- c(
|
||||
'/home/user1/tmp/coverage/test',
|
||||
'/home/user1/tmp/covert/operator',
|
||||
'/home/user1/tmp/coven/members')
|
||||
|
||||
get_common_dir(paths) # "/home/user1/tmp"
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/*REXX program finds common directory path for a list of files. */
|
||||
@.= /*define all file lists to null. */
|
||||
@.1 = '/home/user1/tmp/coverage/test'
|
||||
@.2 = '/home/user1/tmp/covert/operator'
|
||||
@.3 = '/home/user1/tmp/coven/members'
|
||||
L=length(@.1)
|
||||
do j=2 while @.j\=='' /*start with the second string. */
|
||||
_ = compare(@.j,@.1); if _==0 then iterate /*equal.*/
|
||||
L = min(L,_) /*find the minimum equal strings.*/
|
||||
end /*j*/
|
||||
|
||||
common = left(@.1,lastpos('/',@.1,L)) /*find the shortest DIR string.*/
|
||||
if right(common,1)=='/' then common=left(common, max(0,length(common)-1))
|
||||
say 'common directory path: ' common /*[↑] handle trailing / delimiter*/
|
||||
/*stick a fork in it, we're done.*/
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
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"
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
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"
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package require Tcl 8.5
|
||||
proc pop {varname} {
|
||||
upvar 1 $varname var
|
||||
set var [lassign $var head]
|
||||
return $head
|
||||
}
|
||||
|
||||
proc common_prefix {dirs {separator "/"}} {
|
||||
set parts [split [pop dirs] $separator]
|
||||
while {[llength $dirs]} {
|
||||
set r {}
|
||||
foreach cmp $parts elt [split [pop dirs] $separator] {
|
||||
if {$cmp ne $elt} break
|
||||
lappend r $cmp
|
||||
}
|
||||
set parts $r
|
||||
}
|
||||
return [join $parts $separator]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue