Shell Glob Golfing

11

Эта задача - вывести кратчайший путь к файлу после расширения глобуса.

Что такое ракушка? В большинстве оболочек вы можете использовать *символ в пути для представления любых символов в позиции. Например, если каталог fooсодержит файлы bar bazи asdf, то foo/b*развернется до foo/bar foo/baz.

Теперь предположим, что текущий каталог содержит файл с именем ihavealongnameи ничего больше. Если я хочу сослаться на этот файл, я мог бы напечатать *, который будет представлять только этот один файл, вместо того, чтобы вводить полное имя.

Если каталог также содержит файл с именем ialsohavealongname, я не могу сделать *, так как он будет соответствовать обоим файлам. Я должен сделать, по крайней мере, ih*.

*Модель также работает для сравнения каталогов выше файла я ищу. Если есть только две директории fooи bar, но fooсодержит только файл bazи barсодержит файл asdf, я могу соответствовать foo/bazс */baz. Или, еще более лаконично, */b*. Если бы barбыло пусто, */*работало бы.

Ваша задача: учитывая строковый массив путей, которые представляют «текущий каталог», и один целевой путь, выведите кратчайшую возможную строку, которая будет расширена только до этого целевого пути после расширения * s.

Целевой путь может быть взят как его собственная строка, как индекс в массиве путей, как первый элемент в массиве переданных путей, или каким-либо другим удобным способом, который не является жестким кодированием. Спросите в комментариях, если не уверены.

Целевой путь гарантированно присутствует в «текущем каталоге».

Вы можете предположить, что все пути содержат только буквенно-цифровые ASCII (и /). Вы можете использовать в качестве входных путей корневые (начинаются с /) или относительные (не начинайте с /).

Если есть несколько одинаково коротких возможностей, верните одну или все из них.

Это , побеждает наименьшее количество байтов!

Тестовые случаи , благодаря Кевину Круйссену .

Павел
источник
4
Таким образом , мы можем предположить , имена файлов не содержат пробелы, переводы строк, обратные косые, *, ?, и [ т.д.? Возможно, будет проще, если вы просто заявите, что имена файлов и каталогов буквенно-цифровые
Тон Хоспел
3
Фактическая часть дискового ввода / вывода будет скучной на многих языках. например, в perl я бы просто взял имя файла и заменил все компоненты пути на *и запустил perl, globчтобы получить все имена файлов, которые могут иметь отношение (например, foo/bar/bazстановится */*/*). После этого это становится задачей обработки строк. И этот вызов уже достаточно сложен. Я думаю, что этот вызов будет чище, так как «учитывая список буквенно-цифровых (и /) относительных путей, найдите кратчайший глобус, который соответствует только этому существующему целевому пути
Тон Хоспел
1
@KevinCruijssen Конечно, это забавная задача, и в основном она должна держать в чистоте языки игры в гольф. Я думаю, что вам понадобится настоящая программа (если вы не сгенерируете все возможные строки, пока не дойдете до самой короткой, которая работает, что скучно и экспоненциально взорвется). Ваши текущие примеры едва начать покрывать дела, которые вам нужно решить. Вот пыльники случай: использование a*fдля выбора azzfиз azzf, azzg, bzzf. Расширение по желанию и a*b*cт.д ..
Тон Хоспель
2
@TonHospel Я убежден. Теперь вы берете массив путей в качестве входных данных.
Павел
4
@ WeijunZhou Я передумал о вводе. Теперь вы можете взять массив путей.
Павел

Ответы:

8

Perl 5 , 136 107 102 байт

Включает +2в себяn0

Дайте список файлов на STDIN. Первый считается целевым файлом

perl -n0E '@a="";for$a(@a){s%%s/(?=$a
)/;/g;$$_//=push@a,map$_.$a,/./g,"\\w*";/^;/>/
;/&&1/!say$a=~s/\\w//gr%e}'
foo/barber/test
foo/barber/testing
foo/barber/coding
foo/test
foo/bar/test
^D

Просто код, не делающий переводы строк буквальными:

@a="";for$a(@a){s%%s/(?=$a\n)/;/g;$$_//=push@a,map$_.$a,/./g,"\\w*";/^;/>/\n;/&&1/!say$a=~s/\\w//gr%e}

Преднамеренно вылетает после печати решения.

Все еще кажется слишком длинным (использование $aи 1/0очень неудобно), но это начало и должно быть достаточно эффективным.

Попробуйте онлайн!

Как это работает

Программа создает потенциальные глобусы, увеличивая их сзади и вперед, начиная с пустой строки. Он делает это в ширину первого пути, так что первые шарики длины 0 судят (только ``), то длина 1 (например t, i, *), следующая длина 2 (как fb, i*, *g, **), следующая длина 3 и так далее до тех пор , найден глобус, который соответствует только первому пути. Тогда это будет самый короткий шар, который решит проблему (могут существовать другие с одинаковой длиной).

Глобусы длины n+1генерируются из глобусов длины nпутем добавления каждого символа из списка путей, а также *перед каждым глобаном длины n. Так , например , длина 3 Глобы *i*будет способствовать длине 4 шариков f*i*, o*i*, o*i*, /*i*, b*i*... s*i*, t*i*и , наконец **i*. Обратите внимание, что к каждому символу из списка входных путей добавляется префикс, даже если он появляется несколько раз или вообще не имеет смысла, поскольку приводит к чему-то, что никогда не может совпадать.

Выполнение этого наивно приведет к комбинаторному взрыву. Вот почему каждый потенциальный глоб оценивается на предмет его полезности, определяя, в каких точках путей он мог бы соответствовать, если глобус использовался в конце полного глобуса. Я делаю это, вставляя ;в каждое место, где возможно совпадение. Например, для глобуса t*я получу строку:

foo/barber/;tes;t
foo/barber/;tes;ting
foo/barber/coding
foo/;tes;t
foo/bar/;tes;t

Это представляет собой «отличительную силу» шара. Каждый шар, который имеет точно такую ​​же отличительную силу, одинаково хорош. Если вы замените их друг на друга в конце полного шара, все они будут совпадать с одинаковыми путями. Так что вы можете использовать самый короткий.

Поэтому, рассматривая длину nшариков, я сначала смотрю на их отличительную силу. Если это было замечено ранее, был еще один шар длиной nили короче, который уже был рассмотрен и расширен, так что этот шар бессмысленен и обрезается. Это, например, избавит от кандидатов, как, **i*так как та же самая отличительная сила уже была замечена как *i*. Это также сокращает невозможных кандидатов, как, f*i*так как отличительная строка не будет иметь;и просто быть оригинальным списком путей. Будет принят только самый первый невозможный шар, все остальные будут иметь одинаковую способность различения и будут обрезаны. И даже это первое не будет расширено, так как все расширения все еще невозможны и будут сокращены, когда они будут рассмотрены. Одновременно in*обрезается и i*т. Д.

Вышеуказанное приводит к очень агрессивному сокращению, и поэтому программа способна обрабатывать сложные случаи за очень короткое время. Однако главная неэффективность заключается в том, что в префиксах глобусов-кандидатов ставятся все возможные символы, а не только те, которые находятся непосредственно перед ;целевым путем пути отличительной строки. Все добавленные символы, которые не находятся перед a ;, не являются проблемой, поскольку они приводят к невозможному глобу, который будет обрезан, когда он будет рассмотрен, но при этом все равно оставит символы непосредственно перед ;другими путями. Таким образом, в конце концов, программа также создает глобусы, которые смогут соответствовать любой комбинации заданных путей. Он понятия не имеет, что он должен концентрироваться на первом пути.

Теперь рассмотрим решение проблемы. В приведенном примере это может быть */*er/t. Это дает следующую отличительную строку:

;f;o;o;/barber/test
foo/barber/testing
foo/barber/coding
foo/test
foo/bar/test

Я распознаю решение по наличию ;в первой позиции (так, чтобы оно соответствовало первому пути) и отсутствию ;в начале любого другого пути (чтобы другие не совпадали)

С объясненным алгоритмом я теперь перехожу к реальной программе:

Глобусы-кандидаты будут в массиве, @aкоторый я зациклю, используя переменную, $aкоторая содержит глобус, который в данный момент находится на рассмотрении. Вместо того, чтобы *в глобусе, я, однако, буду использовать, \w*так что $aэто на самом деле регулярное выражение вместо глобуса. Я собираюсь злоупотреблять странностью цикла perl for, который заключается в том, что вы можете добавлять элементы в зацикленный массив во время выполнения цикла, и эти новые элементы будут выбраны в цикле. Поскольку при генерации n+1глобусов длины все глобусы длины nуже находятся в массиве, @aэто ширина в первую очередь.

Благодаря -n0опции (неявный цикл по всему входу) список путей представлен в $_виде одной большой строки с каждым путем, оканчивающимся новой строкой

@a="";                    Start everything with the length 0 glob
for$a(@a){    }           Loop over candidates in a breadth first way

Внутри у { }нас есть:

s/(?=$a\n)/;/g            Loop over the paths and insert a ; at every
                          position that the suffix glob can match by
                          looking ahead and checking that the regex
                          under consideration can match up to the end of
                          the path we are in. The distinguishing sting is
                          now in `$_`.

Ой, я только что уничтожил, $_и он мне понадобится для следующего цикла. Так что оберните фактический рабочий код внутри

s%%  ...code.. %e

Это соответствует пустой строке в начале $_и позволяет запустить код, чтобы определить, чем он будет заменен. Если я убедлюсь, что этот код оценивается как пустая строка $_, в конце она останется неизменной, даже если я изменю $_во время code.

Возвращаясь сразу после того, как я заменил $_отличительную строку:

$$_//= expression

Это как:

$seen{$_} //= expression

//в перл есть 'defined or. Это похоже на короткое замыкание, orкогда второй аргумент оценивается, только если первый аргумент undef. И это может быть объединено с заданием, как +=в некоторых других языках. Так что, если они ключ $_в хэш %seenявляется undef(это то , что вы получите при обращении к несуществующему элементу) только тогда выполнить выражение и назначить его в качестве значения для ключа $_. Поэтому, если я уверен, expressionчто не возвращает, undefэто в основном означает «вычислять выражение тогда и только тогда, когда мы впервые видим эту конкретную отличительную строку». И поскольку $_он гарантированно содержит a, \nфактически безопасно использовать глобальный хеш perl для хранения отличительных строк, поэтому $$_вместо$seen{$_}

Для expressionиспользования I:

push@a,map$_.$a,/./g,"\\w*"

В основном «Для каждого символа (кроме новой строки) в отличительной строке, а также *добавьте его к текущему глобу и вставьте его в массив глобусов-кандидатов». За исключением того, что я использую \w*для *получения правильного регулярного выражения (я мог бы использовать ''вместо того, ""чтобы избавиться от одной обратной косой черты, но тогда я не мог запустить свой код из командной строки). Обратите внимание, что это также поднимает ;и добавляет их к кандидатным глобусам, но при последующем тестировании их на восстановленных, у $_которых нет ;, снова будет невозможный глобус и будет сокращен.

/^;/>/\n;/ &&      If the distinguishing string corresponds to a solution

say$a=~s/\\w//gr   Then replace all \w* back to * and print the solution

1/!                Say returns 1 so this becomes a division by 0.
                   The program exits by crashing after solving it

Обратите внимание, что /^;/>/\n;/значение эквивалентно пустой строке, если решение еще не найдено, поэтому оно будет функционировать как пустая замещающая строка и $_будет восстановлено

Тон Хоспел
источник
Я получаю ошибку на TIO, но она работает локально. Вы знаете, почему это так?
Павел
1
@Pavel -EАктивирует последний уровень языка. Вам нужен по крайней мере Perl, 5.10.0чтобы иметь возможность использовать say. Так что ставьте use 5.10.0;в шапку раздел и все будет работать. Варианты, чтобы установить уровень языка в любом случае бесплатно, даже если вы не можете сделать это с помощью -E. На самом деле все варианты считаются бесплатными в настоящее время (так что мне даже не нужно их считать n0), но я считаю, что это слишком снисходительно для Perl
Тон Хоспел
2
Выход с ошибкой - это нормально , поэтому ваше 1/решение действительно! Мне тоже нужно это помнить ...
Дом Гастингс,
7

Java 10, 854 824 796 738 728 703 688 655 652 647 624 байта

import java.util.*;a->f->{var L=new Stack();List<String>s;int i=999,j,k;for(var t:f.split("/")){s=new java.util.concurrent.CopyOnWriteArrayList();s.add(t);for(k=1;k>0;){k=0;for(var x:s)for(j=0;j<x.length();)if(!s.contains(f=x.substring(0,j)+"~"+x.substring(++j))){s.add(f);k=1;}}for(var x:s)s.add(x.replaceAll("~+","\\*"));L.add(s);}p(L,s=new Stack(),0,f="");for(var y:s){k=0;for(var x:a)if(x.matches(y.replace("*",".*"))&x.split("/").length==y.split("/").length)k++;if(k==1&(j=y.length())<i){f=y;i=j;}}return f;};void p(List L,List r,int d,String c){if(d==L.size())r.add(c);else for(var o:(List)L.get(d))p(L,r,d+1,c+"/"+o);}

Какой беспорядок ... Это, конечно, нелегкая задача в Java. Определенно может быть в гольфе на пару сотен байтов, но я просто рад, что это наконец работает. А я говорил тебе. :)
-5 байт благодаря @ceilingcat .
-23 байта при переключении с Java 8 на Java 10

Ввод в виде String-массива путей к файлам (с каталогами в виде отдельных элементов и всеми элементами, содержащими /начальные символы) и String с входным путем к файлу для поиска.

Объяснение:

Попробуйте онлайн. (Тестовые случаи с ialsohavealongname/ ihavealongnameaswellнемного сокращены по длине и s.add(x.replaceAll("~+","\\*"));были заменены {s.remove(x);s.add(x.replaceAll("~+","\\*"));}на работу через 5-10 секунд на TIO вместо тайм-аута через 60 с.)

import java.util.*;   // Required import for List and Stack

// Method with String-array and String parameters and String return-type
a->f->{
  var L=new Stack();  //  Create a List of Lists
  List<String>s;      //  List of Strings (uninitialized)
  int i=999,j,k;      //  Three integers (`i` starting at 999,
                      //   because 260 is the maximum file-path length in Windows)
  for(var t:f.split("/")){
                      //  Loop over the input file-path split by "/":
    s=new java.util.concurrent.CopyOnWriteArrayList();
                      //  Create a List (which we can modify while iterating it)
    s.add(t);         //  Add the input to this List
    for(k=1;k>0;){    //  Loop as long as there are new items added to the List
      k=0;            //   Reset the newAdded-flag to false
      for(var x:s)    //   And inner loop over the List
        for(j=0;j<t.length();)
                      //    Inner loop `j` in range [0,length-of-item):
          if(!s.contains(f=x.substring(0,j)+"~"+x.substring(++j))){
                      //     Replace the character at index `j` with a '~'
                      //     And if it's a new item:
            s.add(f); //      Add it to the List
            k=1;}}    //      And set the newAdded-flag to true
    for(var x:s)      //  Loop over the List again
      s.add(x.replaceAll("~+","\\*")));
                      //   And replace all 1 or more '~' with a single asterisk
                      //   (NOTE: To reduce bytes it doesn't remove the existing items)
    L.add(s);}        //   Add this List to the List of Lists
  p(L,s=new Stack(),0,"");
                      //  Generate all permutations of the groppings
                      //  (List `s` now contains all groppings of the given file-path)
  for(var y:s){       //  Loop over the groppings in the String-List:
    k=0;              //   Reset integer `k` to 0
    for(var x:a)      //   Inner loop over the input file-paths:
      if(x.matches(y.replace("*",".*"))
                      //    If the current file-path matches the current gropping
         x.split("/").length==y.split("/").length)
                      //    and the amount of slashes are the same:
         k++;         //     Increase integer `k` by 1
    if(k==1           //   If only one of the file-paths matched,
       &(j=y.length())<i){
                      //   and the length is shorter than `i`:
      f=y;            //    Replace the result with this gropping file-path
      i=j;}}          //    And also replace `i` with this shorter `j`
  return f;}          //  Finally return this shortest gropping file-path

// Separated method to generate gropping file-path permutations given a List of Lists
void p(List L,List r,int d,String c){
  if(d==L.size())     //  If we've reached the final depth
    r.add(c);         //   Add the current gropping-file path to the result-List
  else                //  Else:
    for(var o:(List)L.get(d))
                      //   Loop over the List of the current depth:
      p(L,r,d+1,      //    Recursive call with depth+1,
        c+"/"+o);}    //    and current + "/" + item of loop

Дополнительное общее объяснение:

Пример: возьмем /foo, /foo/bar, /foo/barber, /foo/bar/test, /foo/barber/test, /foo/barber/testing, /foo/barber/coding, /foo/testкак заданные пути к файлам, так и foo/bar/testкак входной путь к файлу для поиска.

1) Я начинаю с разбиения ввода пути к /файлу и генерирую все сопоставления файлов этих разделенных слов:

foo: [foo, *oo, f*o, fo*, *o, *o*, f*, *]
bar: [bar, *ar, b*r, ba*, *r, *a*, b*, *]
test: [test, *est, t*st, te*t, tes*, *st, *e*t, *es*, t*t, t*s*, te*, *t, *s*, *e*, t*, *]

2) Затем я генерирую все перестановки с этими словами в том же порядке (повторно применяя /между ними и спереди):

[/foo/bar/test, /foo/bar/*est, /foo/bar/t*st, /foo/bar/te*t, /foo/bar/tes*, /foo/bar/*st, /foo/bar/*e*t, /foo/bar/*es*, /foo/bar/t*t, /foo/bar/t*s*, /foo/bar/te*, /foo/bar/*t, /foo/bar/*s*, /foo/bar/*e*, /foo/bar/t*, /foo/bar/*, /foo/*ar/test, /foo/*ar/*est, /foo/*ar/t*st, /foo/*ar/te*t, /foo/*ar/tes*, /foo/*ar/*st, /foo/*ar/*e*t, /foo/*ar/*es*, /foo/*ar/t*t, /foo/*ar/t*s*, /foo/*ar/te*, /foo/*ar/*t, /foo/*ar/*s*, /foo/*ar/*e*, /foo/*ar/t*, /foo/*ar/*, /foo/b*r/test, /foo/b*r/*est, /foo/b*r/t*st, /foo/b*r/te*t, /foo/b*r/tes*, /foo/b*r/*st, /foo/b*r/*e*t, /foo/b*r/*es*, /foo/b*r/t*t, /foo/b*r/t*s*, /foo/b*r/te*, /foo/b*r/*t, /foo/b*r/*s*, /foo/b*r/*e*, /foo/b*r/t*, /foo/b*r/*, /foo/ba*/test, /foo/ba*/*est, /foo/ba*/t*st, /foo/ba*/te*t, /foo/ba*/tes*, /foo/ba*/*st, /foo/ba*/*e*t, /foo/ba*/*es*, /foo/ba*/t*t, /foo/ba*/t*s*, /foo/ba*/te*, /foo/ba*/*t, /foo/ba*/*s*, /foo/ba*/*e*, /foo/ba*/t*, /foo/ba*/*, /foo/*r/test, /foo/*r/*est, /foo/*r/t*st, /foo/*r/te*t, /foo/*r/tes*, /foo/*r/*st, /foo/*r/*e*t, /foo/*r/*es*, /foo/*r/t*t, /foo/*r/t*s*, /foo/*r/te*, /foo/*r/*t, /foo/*r/*s*, /foo/*r/*e*, /foo/*r/t*, /foo/*r/*, /foo/*a*/test, /foo/*a*/*est, /foo/*a*/t*st, /foo/*a*/te*t, /foo/*a*/tes*, /foo/*a*/*st, /foo/*a*/*e*t, /foo/*a*/*es*, /foo/*a*/t*t, /foo/*a*/t*s*, /foo/*a*/te*, /foo/*a*/*t, /foo/*a*/*s*, /foo/*a*/*e*, /foo/*a*/t*, /foo/*a*/*, /foo/b*/test, /foo/b*/*est, /foo/b*/t*st, /foo/b*/te*t, /foo/b*/tes*, /foo/b*/*st, /foo/b*/*e*t, /foo/b*/*es*, /foo/b*/t*t, /foo/b*/t*s*, /foo/b*/te*, /foo/b*/*t, /foo/b*/*s*, /foo/b*/*e*, /foo/b*/t*, /foo/b*/*, /foo/*/test, /foo/*/*est, /foo/*/t*st, /foo/*/te*t, /foo/*/tes*, /foo/*/*st, /foo/*/*e*t, /foo/*/*es*, /foo/*/t*t, /foo/*/t*s*, /foo/*/te*, /foo/*/*t, /foo/*/*s*, /foo/*/*e*, /foo/*/t*, /foo/*/*, /*oo/bar/test, /*oo/bar/*est, /*oo/bar/t*st, /*oo/bar/te*t, /*oo/bar/tes*, /*oo/bar/*st, /*oo/bar/*e*t, /*oo/bar/*es*, /*oo/bar/t*t, /*oo/bar/t*s*, /*oo/bar/te*, /*oo/bar/*t, /*oo/bar/*s*, /*oo/bar/*e*, /*oo/bar/t*, /*oo/bar/*, /*oo/*ar/test, /*oo/*ar/*est, /*oo/*ar/t*st, /*oo/*ar/te*t, /*oo/*ar/tes*, /*oo/*ar/*st, /*oo/*ar/*e*t, /*oo/*ar/*es*, /*oo/*ar/t*t, /*oo/*ar/t*s*, /*oo/*ar/te*, /*oo/*ar/*t, /*oo/*ar/*s*, /*oo/*ar/*e*, /*oo/*ar/t*, /*oo/*ar/*, /*oo/b*r/test, /*oo/b*r/*est, /*oo/b*r/t*st, /*oo/b*r/te*t, /*oo/b*r/tes*, /*oo/b*r/*st, /*oo/b*r/*e*t, /*oo/b*r/*es*, /*oo/b*r/t*t, /*oo/b*r/t*s*, /*oo/b*r/te*, /*oo/b*r/*t, /*oo/b*r/*s*, /*oo/b*r/*e*, /*oo/b*r/t*, /*oo/b*r/*, /*oo/ba*/test, /*oo/ba*/*est, /*oo/ba*/t*st, /*oo/ba*/te*t, /*oo/ba*/tes*, /*oo/ba*/*st, /*oo/ba*/*e*t, /*oo/ba*/*es*, /*oo/ba*/t*t, /*oo/ba*/t*s*, /*oo/ba*/te*, /*oo/ba*/*t, /*oo/ba*/*s*, /*oo/ba*/*e*, /*oo/ba*/t*, /*oo/ba*/*, /*oo/*r/test, /*oo/*r/*est, /*oo/*r/t*st, /*oo/*r/te*t, /*oo/*r/tes*, /*oo/*r/*st, /*oo/*r/*e*t, /*oo/*r/*es*, /*oo/*r/t*t, /*oo/*r/t*s*, /*oo/*r/te*, /*oo/*r/*t, /*oo/*r/*s*, /*oo/*r/*e*, /*oo/*r/t*, /*oo/*r/*, /*oo/*a*/test, /*oo/*a*/*est, /*oo/*a*/t*st, /*oo/*a*/te*t, /*oo/*a*/tes*, /*oo/*a*/*st, /*oo/*a*/*e*t, /*oo/*a*/*es*, /*oo/*a*/t*t, /*oo/*a*/t*s*, /*oo/*a*/te*, /*oo/*a*/*t, /*oo/*a*/*s*, /*oo/*a*/*e*, /*oo/*a*/t*, /*oo/*a*/*, /*oo/b*/test, /*oo/b*/*est, /*oo/b*/t*st, /*oo/b*/te*t, /*oo/b*/tes*, /*oo/b*/*st, /*oo/b*/*e*t, /*oo/b*/*es*, /*oo/b*/t*t, /*oo/b*/t*s*, /*oo/b*/te*, /*oo/b*/*t, /*oo/b*/*s*, /*oo/b*/*e*, /*oo/b*/t*, /*oo/b*/*, /*oo/*/test, /*oo/*/*est, /*oo/*/t*st, /*oo/*/te*t, /*oo/*/tes*, /*oo/*/*st, /*oo/*/*e*t, /*oo/*/*es*, /*oo/*/t*t, /*oo/*/t*s*, /*oo/*/te*, /*oo/*/*t, /*oo/*/*s*, /*oo/*/*e*, /*oo/*/t*, /*oo/*/*, /f*o/bar/test, /f*o/bar/*est, /f*o/bar/t*st, /f*o/bar/te*t, /f*o/bar/tes*, /f*o/bar/*st, /f*o/bar/*e*t, /f*o/bar/*es*, /f*o/bar/t*t, /f*o/bar/t*s*, /f*o/bar/te*, /f*o/bar/*t, /f*o/bar/*s*, /f*o/bar/*e*, /f*o/bar/t*, /f*o/bar/*, /f*o/*ar/test, /f*o/*ar/*est, /f*o/*ar/t*st, /f*o/*ar/te*t, /f*o/*ar/tes*, /f*o/*ar/*st, /f*o/*ar/*e*t, /f*o/*ar/*es*, /f*o/*ar/t*t, /f*o/*ar/t*s*, /f*o/*ar/te*, /f*o/*ar/*t, /f*o/*ar/*s*, /f*o/*ar/*e*, /f*o/*ar/t*, /f*o/*ar/*, /f*o/b*r/test, /f*o/b*r/*est, /f*o/b*r/t*st, /f*o/b*r/te*t, /f*o/b*r/tes*, /f*o/b*r/*st, /f*o/b*r/*e*t, /f*o/b*r/*es*, /f*o/b*r/t*t, /f*o/b*r/t*s*, /f*o/b*r/te*, /f*o/b*r/*t, /f*o/b*r/*s*, /f*o/b*r/*e*, /f*o/b*r/t*, /f*o/b*r/*, /f*o/ba*/test, /f*o/ba*/*est, /f*o/ba*/t*st, /f*o/ba*/te*t, /f*o/ba*/tes*, /f*o/ba*/*st, /f*o/ba*/*e*t, /f*o/ba*/*es*, /f*o/ba*/t*t, /f*o/ba*/t*s*, /f*o/ba*/te*, /f*o/ba*/*t, /f*o/ba*/*s*, /f*o/ba*/*e*, /f*o/ba*/t*, /f*o/ba*/*, /f*o/*r/test, /f*o/*r/*est, /f*o/*r/t*st, /f*o/*r/te*t, /f*o/*r/tes*, /f*o/*r/*st, /f*o/*r/*e*t, /f*o/*r/*es*, /f*o/*r/t*t, /f*o/*r/t*s*, /f*o/*r/te*, /f*o/*r/*t, /f*o/*r/*s*, /f*o/*r/*e*, /f*o/*r/t*, /f*o/*r/*, /f*o/*a*/test, /f*o/*a*/*est, /f*o/*a*/t*st, /f*o/*a*/te*t, /f*o/*a*/tes*, /f*o/*a*/*st, /f*o/*a*/*e*t, /f*o/*a*/*es*, /f*o/*a*/t*t, /f*o/*a*/t*s*, /f*o/*a*/te*, /f*o/*a*/*t, /f*o/*a*/*s*, /f*o/*a*/*e*, /f*o/*a*/t*, /f*o/*a*/*, /f*o/b*/test, /f*o/b*/*est, /f*o/b*/t*st, /f*o/b*/te*t, /f*o/b*/tes*, /f*o/b*/*st, /f*o/b*/*e*t, /f*o/b*/*es*, /f*o/b*/t*t, /f*o/b*/t*s*, /f*o/b*/te*, /f*o/b*/*t, /f*o/b*/*s*, /f*o/b*/*e*, /f*o/b*/t*, /f*o/b*/*, /f*o/*/test, /f*o/*/*est, /f*o/*/t*st, /f*o/*/te*t, /f*o/*/tes*, /f*o/*/*st, /f*o/*/*e*t, /f*o/*/*es*, /f*o/*/t*t, /f*o/*/t*s*, /f*o/*/te*, /f*o/*/*t, /f*o/*/*s*, /f*o/*/*e*, /f*o/*/t*, /f*o/*/*, /fo*/bar/test, /fo*/bar/*est, /fo*/bar/t*st, /fo*/bar/te*t, /fo*/bar/tes*, /fo*/bar/*st, /fo*/bar/*e*t, /fo*/bar/*es*, /fo*/bar/t*t, /fo*/bar/t*s*, /fo*/bar/te*, /fo*/bar/*t, /fo*/bar/*s*, /fo*/bar/*e*, /fo*/bar/t*, /fo*/bar/*, /fo*/*ar/test, /fo*/*ar/*est, /fo*/*ar/t*st, /fo*/*ar/te*t, /fo*/*ar/tes*, /fo*/*ar/*st, /fo*/*ar/*e*t, /fo*/*ar/*es*, /fo*/*ar/t*t, /fo*/*ar/t*s*, /fo*/*ar/te*, /fo*/*ar/*t, /fo*/*ar/*s*, /fo*/*ar/*e*, /fo*/*ar/t*, /fo*/*ar/*, /fo*/b*r/test, /fo*/b*r/*est, /fo*/b*r/t*st, /fo*/b*r/te*t, /fo*/b*r/tes*, /fo*/b*r/*st, /fo*/b*r/*e*t, /fo*/b*r/*es*, /fo*/b*r/t*t, /fo*/b*r/t*s*, /fo*/b*r/te*, /fo*/b*r/*t, /fo*/b*r/*s*, /fo*/b*r/*e*, /fo*/b*r/t*, /fo*/b*r/*, /fo*/ba*/test, /fo*/ba*/*est, /fo*/ba*/t*st, /fo*/ba*/te*t, /fo*/ba*/tes*, /fo*/ba*/*st, /fo*/ba*/*e*t, /fo*/ba*/*es*, /fo*/ba*/t*t, /fo*/ba*/t*s*, /fo*/ba*/te*, /fo*/ba*/*t, /fo*/ba*/*s*, /fo*/ba*/*e*, /fo*/ba*/t*, /fo*/ba*/*, /fo*/*r/test, /fo*/*r/*est, /fo*/*r/t*st, /fo*/*r/te*t, /fo*/*r/tes*, /fo*/*r/*st, /fo*/*r/*e*t, /fo*/*r/*es*, /fo*/*r/t*t, /fo*/*r/t*s*, /fo*/*r/te*, /fo*/*r/*t, /fo*/*r/*s*, /fo*/*r/*e*, /fo*/*r/t*, /fo*/*r/*, /fo*/*a*/test, /fo*/*a*/*est, /fo*/*a*/t*st, /fo*/*a*/te*t, /fo*/*a*/tes*, /fo*/*a*/*st, /fo*/*a*/*e*t, /fo*/*a*/*es*, /fo*/*a*/t*t, /fo*/*a*/t*s*, /fo*/*a*/te*, /fo*/*a*/*t, /fo*/*a*/*s*, /fo*/*a*/*e*, /fo*/*a*/t*, /fo*/*a*/*, /fo*/b*/test, /fo*/b*/*est, /fo*/b*/t*st, /fo*/b*/te*t, /fo*/b*/tes*, /fo*/b*/*st, /fo*/b*/*e*t, /fo*/b*/*es*, /fo*/b*/t*t, /fo*/b*/t*s*, /fo*/b*/te*, /fo*/b*/*t, /fo*/b*/*s*, /fo*/b*/*e*, /fo*/b*/t*, /fo*/b*/*, /fo*/*/test, /fo*/*/*est, /fo*/*/t*st, /fo*/*/te*t, /fo*/*/tes*, /fo*/*/*st, /fo*/*/*e*t, /fo*/*/*es*, /fo*/*/t*t, /fo*/*/t*s*, /fo*/*/te*, /fo*/*/*t, /fo*/*/*s*, /fo*/*/*e*, /fo*/*/t*, /fo*/*/*, /*o/bar/test, /*o/bar/*est, /*o/bar/t*st, /*o/bar/te*t, /*o/bar/tes*, /*o/bar/*st, /*o/bar/*e*t, /*o/bar/*es*, /*o/bar/t*t, /*o/bar/t*s*, /*o/bar/te*, /*o/bar/*t, /*o/bar/*s*, /*o/bar/*e*, /*o/bar/t*, /*o/bar/*, /*o/*ar/test, /*o/*ar/*est, /*o/*ar/t*st, /*o/*ar/te*t, /*o/*ar/tes*, /*o/*ar/*st, /*o/*ar/*e*t, /*o/*ar/*es*, /*o/*ar/t*t, /*o/*ar/t*s*, /*o/*ar/te*, /*o/*ar/*t, /*o/*ar/*s*, /*o/*ar/*e*, /*o/*ar/t*, /*o/*ar/*, /*o/b*r/test, /*o/b*r/*est, /*o/b*r/t*st, /*o/b*r/te*t, /*o/b*r/tes*, /*o/b*r/*st, /*o/b*r/*e*t, /*o/b*r/*es*, /*o/b*r/t*t, /*o/b*r/t*s*, /*o/b*r/te*, /*o/b*r/*t, /*o/b*r/*s*, /*o/b*r/*e*, /*o/b*r/t*, /*o/b*r/*, /*o/ba*/test, /*o/ba*/*est, /*o/ba*/t*st, /*o/ba*/te*t, /*o/ba*/tes*, /*o/ba*/*st, /*o/ba*/*e*t, /*o/ba*/*es*, /*o/ba*/t*t, /*o/ba*/t*s*, /*o/ba*/te*, /*o/ba*/*t, /*o/ba*/*s*, /*o/ba*/*e*, /*o/ba*/t*, /*o/ba*/*, /*o/*r/test, /*o/*r/*est, /*o/*r/t*st, /*o/*r/te*t, /*o/*r/tes*, /*o/*r/*st, /*o/*r/*e*t, /*o/*r/*es*, /*o/*r/t*t, /*o/*r/t*s*, /*o/*r/te*, /*o/*r/*t, /*o/*r/*s*, /*o/*r/*e*, /*o/*r/t*, /*o/*r/*, /*o/*a*/test, /*o/*a*/*est, /*o/*a*/t*st, /*o/*a*/te*t, /*o/*a*/tes*, /*o/*a*/*st, /*o/*a*/*e*t, /*o/*a*/*es*, /*o/*a*/t*t, /*o/*a*/t*s*, /*o/*a*/te*, /*o/*a*/*t, /*o/*a*/*s*, /*o/*a*/*e*, /*o/*a*/t*, /*o/*a*/*, /*o/b*/test, /*o/b*/*est, /*o/b*/t*st, /*o/b*/te*t, /*o/b*/tes*, /*o/b*/*st, /*o/b*/*e*t, /*o/b*/*es*, /*o/b*/t*t, /*o/b*/t*s*, /*o/b*/te*, /*o/b*/*t, /*o/b*/*s*, /*o/b*/*e*, /*o/b*/t*, /*o/b*/*, /*o/*/test, /*o/*/*est, /*o/*/t*st, /*o/*/te*t, /*o/*/tes*, /*o/*/*st, /*o/*/*e*t, /*o/*/*es*, /*o/*/t*t, /*o/*/t*s*, /*o/*/te*, /*o/*/*t, /*o/*/*s*, /*o/*/*e*, /*o/*/t*, /*o/*/*, /*o*/bar/test, /*o*/bar/*est, /*o*/bar/t*st, /*o*/bar/te*t, /*o*/bar/tes*, /*o*/bar/*st, /*o*/bar/*e*t, /*o*/bar/*es*, /*o*/bar/t*t, /*o*/bar/t*s*, /*o*/bar/te*, /*o*/bar/*t, /*o*/bar/*s*, /*o*/bar/*e*, /*o*/bar/t*, /*o*/bar/*, /*o*/*ar/test, /*o*/*ar/*est, /*o*/*ar/t*st, /*o*/*ar/te*t, /*o*/*ar/tes*, /*o*/*ar/*st, /*o*/*ar/*e*t, /*o*/*ar/*es*, /*o*/*ar/t*t, /*o*/*ar/t*s*, /*o*/*ar/te*, /*o*/*ar/*t, /*o*/*ar/*s*, /*o*/*ar/*e*, /*o*/*ar/t*, /*o*/*ar/*, /*o*/b*r/test, /*o*/b*r/*est, /*o*/b*r/t*st, /*o*/b*r/te*t, /*o*/b*r/tes*, /*o*/b*r/*st, /*o*/b*r/*e*t, /*o*/b*r/*es*, /*o*/b*r/t*t, /*o*/b*r/t*s*, /*o*/b*r/te*, /*o*/b*r/*t, /*o*/b*r/*s*, /*o*/b*r/*e*, /*o*/b*r/t*, /*o*/b*r/*, /*o*/ba*/test, /*o*/ba*/*est, /*o*/ba*/t*st, /*o*/ba*/te*t, /*o*/ba*/tes*, /*o*/ba*/*st, /*o*/ba*/*e*t, /*o*/ba*/*es*, /*o*/ba*/t*t, /*o*/ba*/t*s*, /*o*/ba*/te*, /*o*/ba*/*t, /*o*/ba*/*s*, /*o*/ba*/*e*, /*o*/ba*/t*, /*o*/ba*/*, /*o*/*r/test, /*o*/*r/*est, /*o*/*r/t*st, /*o*/*r/te*t, /*o*/*r/tes*, /*o*/*r/*st, /*o*/*r/*e*t, /*o*/*r/*es*, /*o*/*r/t*t, /*o*/*r/t*s*, /*o*/*r/te*, /*o*/*r/*t, /*o*/*r/*s*, /*o*/*r/*e*, /*o*/*r/t*, /*o*/*r/*, /*o*/*a*/test, /*o*/*a*/*est, /*o*/*a*/t*st, /*o*/*a*/te*t, /*o*/*a*/tes*, /*o*/*a*/*st, /*o*/*a*/*e*t, /*o*/*a*/*es*, /*o*/*a*/t*t, /*o*/*a*/t*s*, /*o*/*a*/te*, /*o*/*a*/*t, /*o*/*a*/*s*, /*o*/*a*/*e*, /*o*/*a*/t*, /*o*/*a*/*, /*o*/b*/test, /*o*/b*/*est, /*o*/b*/t*st, /*o*/b*/te*t, /*o*/b*/tes*, /*o*/b*/*st, /*o*/b*/*e*t, /*o*/b*/*es*, /*o*/b*/t*t, /*o*/b*/t*s*, /*o*/b*/te*, /*o*/b*/*t, /*o*/b*/*s*, /*o*/b*/*e*, /*o*/b*/t*, /*o*/b*/*, /*o*/*/test, /*o*/*/*est, /*o*/*/t*st, /*o*/*/te*t, /*o*/*/tes*, /*o*/*/*st, /*o*/*/*e*t, /*o*/*/*es*, /*o*/*/t*t, /*o*/*/t*s*, /*o*/*/te*, /*o*/*/*t, /*o*/*/*s*, /*o*/*/*e*, /*o*/*/t*, /*o*/*/*, /f*/bar/test, /f*/bar/*est, /f*/bar/t*st, /f*/bar/te*t, /f*/bar/tes*, /f*/bar/*st, /f*/bar/*e*t, /f*/bar/*es*, /f*/bar/t*t, /f*/bar/t*s*, /f*/bar/te*, /f*/bar/*t, /f*/bar/*s*, /f*/bar/*e*, /f*/bar/t*, /f*/bar/*, /f*/*ar/test, /f*/*ar/*est, /f*/*ar/t*st, /f*/*ar/te*t, /f*/*ar/tes*, /f*/*ar/*st, /f*/*ar/*e*t, /f*/*ar/*es*, /f*/*ar/t*t, /f*/*ar/t*s*, /f*/*ar/te*, /f*/*ar/*t, /f*/*ar/*s*, /f*/*ar/*e*, /f*/*ar/t*, /f*/*ar/*, /f*/b*r/test, /f*/b*r/*est, /f*/b*r/t*st, /f*/b*r/te*t, /f*/b*r/tes*, /f*/b*r/*st, /f*/b*r/*e*t, /f*/b*r/*es*, /f*/b*r/t*t, /f*/b*r/t*s*, /f*/b*r/te*, /f*/b*r/*t, /f*/b*r/*s*, /f*/b*r/*e*, /f*/b*r/t*, /f*/b*r/*, /f*/ba*/test, /f*/ba*/*est, /f*/ba*/t*st, /f*/ba*/te*t, /f*/ba*/tes*, /f*/ba*/*st, /f*/ba*/*e*t, /f*/ba*/*es*, /f*/ba*/t*t, /f*/ba*/t*s*, /f*/ba*/te*, /f*/ba*/*t, /f*/ba*/*s*, /f*/ba*/*e*, /f*/ba*/t*, /f*/ba*/*, /f*/*r/test, /f*/*r/*est, /f*/*r/t*st, /f*/*r/te*t, /f*/*r/tes*, /f*/*r/*st, /f*/*r/*e*t, /f*/*r/*es*, /f*/*r/t*t, /f*/*r/t*s*, /f*/*r/te*, /f*/*r/*t, /f*/*r/*s*, /f*/*r/*e*, /f*/*r/t*, /f*/*r/*, /f*/*a*/test, /f*/*a*/*est, /f*/*a*/t*st, /f*/*a*/te*t, /f*/*a*/tes*, /f*/*a*/*st, /f*/*a*/*e*t, /f*/*a*/*es*, /f*/*a*/t*t, /f*/*a*/t*s*, /f*/*a*/te*, /f*/*a*/*t, /f*/*a*/*s*, /f*/*a*/*e*, /f*/*a*/t*, /f*/*a*/*, /f*/b*/test, /f*/b*/*est, /f*/b*/t*st, /f*/b*/te*t, /f*/b*/tes*, /f*/b*/*st, /f*/b*/*e*t, /f*/b*/*es*, /f*/b*/t*t, /f*/b*/t*s*, /f*/b*/te*, /f*/b*/*t, /f*/b*/*s*, /f*/b*/*e*, /f*/b*/t*, /f*/b*/*, /f*/*/test, /f*/*/*est, /f*/*/t*st, /f*/*/te*t, /f*/*/tes*, /f*/*/*st, /f*/*/*e*t, /f*/*/*es*, /f*/*/t*t, /f*/*/t*s*, /f*/*/te*, /f*/*/*t, /f*/*/*s*, /f*/*/*e*, /f*/*/t*, /f*/*/*, /*/bar/test, /*/bar/*est, /*/bar/t*st, /*/bar/te*t, /*/bar/tes*, /*/bar/*st, /*/bar/*e*t, /*/bar/*es*, /*/bar/t*t, /*/bar/t*s*, /*/bar/te*, /*/bar/*t, /*/bar/*s*, /*/bar/*e*, /*/bar/t*, /*/bar/*, /*/*ar/test, /*/*ar/*est, /*/*ar/t*st, /*/*ar/te*t, /*/*ar/tes*, /*/*ar/*st, /*/*ar/*e*t, /*/*ar/*es*, /*/*ar/t*t, /*/*ar/t*s*, /*/*ar/te*, /*/*ar/*t, /*/*ar/*s*, /*/*ar/*e*, /*/*ar/t*, /*/*ar/*, /*/b*r/test, /*/b*r/*est, /*/b*r/t*st, /*/b*r/te*t, /*/b*r/tes*, /*/b*r/*st, /*/b*r/*e*t, /*/b*r/*es*, /*/b*r/t*t, /*/b*r/t*s*, /*/b*r/te*, /*/b*r/*t, /*/b*r/*s*, /*/b*r/*e*, /*/b*r/t*, /*/b*r/*, /*/ba*/test, /*/ba*/*est, /*/ba*/t*st, /*/ba*/te*t, /*/ba*/tes*, /*/ba*/*st, /*/ba*/*e*t, /*/ba*/*es*, /*/ba*/t*t, /*/ba*/t*s*, /*/ba*/te*, /*/ba*/*t, /*/ba*/*s*, /*/ba*/*e*, /*/ba*/t*, /*/ba*/*, /*/*r/test, /*/*r/*est, /*/*r/t*st, /*/*r/te*t, /*/*r/tes*, /*/*r/*st, /*/*r/*e*t, /*/*r/*es*, /*/*r/t*t, /*/*r/t*s*, /*/*r/te*, /*/*r/*t, /*/*r/*s*, /*/*r/*e*, /*/*r/t*, /*/*r/*, /*/*a*/test, /*/*a*/*est, /*/*a*/t*st, /*/*a*/te*t, /*/*a*/tes*, /*/*a*/*st, /*/*a*/*e*t, /*/*a*/*es*, /*/*a*/t*t, /*/*a*/t*s*, /*/*a*/te*, /*/*a*/*t, /*/*a*/*s*, /*/*a*/*e*, /*/*a*/t*, /*/*a*/*, /*/b*/test, /*/b*/*est, /*/b*/t*st, /*/b*/te*t, /*/b*/tes*, /*/b*/*st, /*/b*/*e*t, /*/b*/*es*, /*/b*/t*t, /*/b*/t*s*, /*/b*/te*, /*/b*/*t, /*/b*/*s*, /*/b*/*e*, /*/b*/t*, /*/b*/*, /*/*/test, /*/*/*est, /*/*/t*st, /*/*/te*t, /*/*/tes*, /*/*/*st, /*/*/*e*t, /*/*/*es*, /*/*/t*t, /*/*/t*s*, /*/*/te*, /*/*/*t, /*/*/*s*, /*/*/*e*, /*/*/t*, /*/*/*]

3) Затем я перебираю элементы в этом списке выше и проверяю, совпадает ли он только с одним путем к файлу во входном массиве путей к файлам. (Я делаю это, проверяя две вещи: одинаковое ли количество косых черт и соответствует ли оно регулярному выражению, в котором каждый *заменяется на .*.)
Если это так: оставьте (первое) самое короткое, которое мы возвращаем в конце.

Кевин Круйссен
источник
Что >>>? Я знаю, что >>это битовый сдвиг вправо.
Павел
2
@Pavel Для натуральных чисел >>>действует так же, как >>. Но для отрицательных целых чисел он изменяет бит четности на 0 (некоторые примеры можно посмотреть здесь, в разделе « >> vs >>> » ). -1>>>1это просто более короткий вариант Integer.MAX_VALUE1<<31будет Integer.MIN_VALUE).
Кевин Круйссен