Закінчення вкладок проти космічної війни


24

Закінчення вкладок проти космічної війни

Таким чином, відбулася велика дискусія щодо того, чи використовувати вкладки чи пробіли для відступу / форматування коду. Чи можете ви допомогти університету вирішити суперечку, перейшовши на неймовірно божевільний унікальний метод форматування.


Ваше завдання - написати повну програму або функцію, яка розширює всі вкладки на чотири пробіли. А потім замінює пробіг n провідних пробілів на "/ (n - дві зірки тут) /". Ви отримаєте вхід через кілька рядків у будь-якому розумному форматі (один рядковий масив рядків для кожного нового рядка. Стовпчастий масив тощо)

Зразок входу безсоромно вкрали . Зауважте, що оскільки вкладки автоматично розширюються на чотири пробіли в SE, я представляю його як символ «^», але ви також повинні обробляти вкладки (кодова точка 0x09). Усі символи "^" являють собою таблицю.

Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
    Not zero so multiply by 256 again to get 65536
    [>++++<-]>[<++++++++>-]<[>++++++++<-]
    +>[>
        # Print "32"
        ++++++++++[>+++++<-]>+.-.[-]<
    <[-]<->] <[>>
        # Print "16"
        +++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
    # Print "8"
    ++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
^this is preceded by a tab
^^two tabs
^^^three tabs etcetera! 

Вибірка зразка

Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
/**/Not zero so multiply by 256 again to get 65536
/**/[>++++<-]>[<++++++++>-]<[>++++++++<-]
/**/+>[>
/******/# Print "32"
/******/++++++++++[>+++++<-]>+.-.[-]<
/**/<[-]<->] <[>>
/******/# Print "16"
/******/+++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
/**/# Print "8"
/**/++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
/**/this is preceded by a tab
/******/two tabs
/**********/three tabs etcetera! 

Оскільки університету потрібен простір для завантаження Vim та Emacs, вам дозволяється дуже мало місця для зберігання вашого коду. Тому це і виграє найкоротший код. Ви можете припустити, що введення добре сформовано, а рядки з менш ніж чотирма пробілами (після заміни вкладок) можуть призвести до не визначеної поведінки.

Відмова від відповідальності

Ця "відмінна" стратегія форматування вийшла люб'язно Geobits і відтворена з його дозволу. Жоден програміст не постраждав під час постановки цього виклику.


1
Чи з'являться вкладки лише на початку рядків (тобто як відступ)? Чи можуть рядки мати змішане відступ (вкладки + пробіли)?
Лінн

20
Хтось, будь ласка, надсилає відповідь, написану в Whitespace .
GuitarPicker

2
Чи слід розглядати рядки, що починаються з цього /*, чи можна вважати, що це не "добре сформований вхід"? Вихідний файл C ++ був би кращим тестом, оскільки його багаторядковий коментар /* */, можливо, порушить деякі відповіді, які замінюють перший і останній провідні пробіли на /, а потім переходять до заповнення пробілів *.
seshoumara

1
Війна закінчилася: medium.com/@hoffa/… (Якщо, мабуть, ви не програмуєте на C, мабуть.)
стакан

1
@RohanJhunjhunwala Отже, я знову задаю своє перше запитання, оскільки мова не йшла про компільований код. Уявіть той самий /* */код C ++, але цього разу на початку рядка. За вашою специфікацією, його слід залишити так, як є. Тут пастка є, і вже помічені помилкові відповіді, що регулярний вираз, як скажімо, /\** /використовується для заповнення цих пробілів // зірочками, перетворить рядок у /***/. Я також бачив це перетворення /*//*/. Я припускаю, що обидва невірно.
seshoumara

Відповіді:


2

V , 21 , 20 байт

Íô/    
Î^hr/hv0r*r/

Спробуйте в Інтернеті!

Це буквально просто прямий портрет моєї відповіді vim. Помітні відмінності:

  • ÍКоманда (Global замінник) автоматично заповнює /gпрапор, який зберігає два байта

  • ô тотожне \t

  • ÎЦе мнемонічне для :%norm, а також заповнює необхідний простір між :%normнабором натискань клавіш.

  • Кінцеве повернення каретки в кінці додається неявно.


27

Vim, 37, 34, 33, 32 байти

:%s/\t/    /g|%norm ^hr/hv0r*r/

Спробуйте в Інтернеті!

Зауважте, що для цього потрібне зворотне повернення каретки (введення) in vim, хоча і не в онлайн-перекладачі.

Для цього використовується перекладач V, оскільки він сумісний із зворотним ходом. Дуже відверте рішення.

Ось подарунок, який дозволяє вам бачити рішення в реальному часі. Для цього використовується трохи старша версія, і я додав кілька додаткових натискань клавіш, щоб зробити її повільніше, щоб ви могли бачити, що відбувається:

введіть тут опис зображення

А ось пояснення, як це працює:

:%s/\t/    /g           "Replace every tab with 4 spaces
|                       "AND
%norm                   "On every line:
      ^                 "  Move to the first non-whitespace char
       h                "  Move one character to the left. If there is none, the command will end here.
         r/             "  Replace it with a slash
           h            "  Move to the left
            v0          "  Visually select everything until the first column
              r*        "  Replace this selection with asterisks
                r/      "  Replace the first character with a slash

Я збирався +1 для використання, gале тоді ви відредагували, щоб не використовувати g: / +1 у будь-якому випадку: D
Пуховик

@downgoat Ха-ха, дякую! Я насправді набагато гордіший за версію, :gоскільки вона зловживає менш відомою функцією: normкоманда буде скасована, якщо ^F<space>не вдасться. Тож :%norm ^F<space>fooпо суті те ж саме, що і :g/^ /norm fooвеселі хамаки Vim. : D
DJMcMayhem

так, я думав, ^ F використовується для розміщення екрана. чи має вона іншу поведінку всередині norm?
Пуховик

1
@downgoat Ха-ха, ні, це не ^F, не дурні <C-f>нотатки. У цьому випадку це ^, перейдіть до першого знака, який не пробігає, і F<space>Котрий знайде перший пробіл за курсором.
DJMcMayhem

ой, це має тепер набагато більше сенсу> _>
Пуховик

11

Perl, 41 байт

s,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,

Виконайте -pпрапор так:

perl -pe 's,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,'
#     ↑   └───────────────────┬───────────────────┘
#     1 byte               40 bytes

Замініть на вкладку (на Bash, спробуйте ввести Control-V Tab.)


1
Те, як perlзамінили цю референцію на місці, я хотів sedби, щоб це теж було.
seshoumara

7

Чеддар , 60 57 56 байт

Збережено 3 байти завдяки @Conor O'Brien

@.sub(/\t/g," "*4).sub(/^ +/gm,i->"/"+"*"*(i.len-2)+"/")

Я б хотів, щоб у Чеддара було краще форматування рядків.

Спробуйте в Інтернеті!

Пояснення

Це функція. @є функціональним властивістю (наприклад, рубіном &:), що дозволяє вам робити такі речі, як: `ar.map (@. head (-1))

@                      // Input
 .sub( /\t/g, " "*4)   // Replace tabs with four spaces
 .sub(
   /^ +/gm,            // Regex matches leading spaces
   i ->                // i is the matched leading spaces
     "/"+              // The / at the beginning
     "*"*(i.len-2)+    // Repeat *s i-2 times
     "/"                // The / at the end
 )

Якщо ви не знайомі з регулярним виразом:

/^ +/gm

це в основному збігається з одним або кількома ( +) пробілами ( ) на початку ( ^) кожного ( g) рядка ( m).


чи працюють буквальні вкладки в регексах чеддера? також /^ +/вистачає як регулярного вираження, оскільки ми можемо припустити, що провідні простори будуть довжиною принаймні 4.
Conor O'Brien

@ ConorO'Brien Я вважаю, що вони є, але я не
проходив

Перед трансформацією вкладки слід замінити.
Conor O'Brien

@ ConorO'Brien о> _> У мене так було спочатку, а потім я змінив
Пуховик

6

Математика, 97 байт

a=StringReplace;a[a[#,"\t"->"    "],StartOfLine~~b:" "..:>"/"<>Table["*",StringLength@b-2]<>"/"]&

Анонімна функція. Приймає рядок як вхідний і повертає рядок як вихідний.


5

Пітон 3, 124 байти

Використовує хороший регекс.

import re
lambda I:re.sub('^\s*(?m)',lambda m:'/'+'*'*len(m.group()[:-2])+'/',re.sub('\t+',lambda g:' '*4*len(g.group()),I))

Ідей це!


4

Java 210 207 байт

Це референтне рішення, яке реалізує його наївно.

void a(String[]a){for(String s:a){s=s.replaceAll("\t", "    ");String x,y="";int j,i=s.length()-(x=s.replaceAll("^\\s+", "")).length();if(i>3){y="/";for(j=0;j++<i-1;)y+="*";y+="/";}System.out.println(y+x);}}

6
Vim: 37 байт, Cheddar: 65 байт, JavaScript: 75 байт, значить, Java на 210 байт: P, чому я не здивований
Пуховик

1
Дуже стислий код у java: P
Rohan Jhunjhunwala

Ви можете змінити останній для циклу , щоб зберегти 1 байт: for(int j=0;++j<i-1;). Також ви можете видалити int попереднє jі поставити його після вже наявного int:int i=s.length()-(x=s.replaceAll("^\\s+", "")).length(),j;
Kevin Cruijssen

чи не може бути лямбда голити байти за допомогою (a) -> {...}?
bunyaCloven

Принаймні, воно все ще читається і не потребує додаткових коментарів: o)
Рене

3

JavaScript ES6, 75 байт

s=>s.replace(/\t/g,"    ").replace(/^ +/gm,k=>`/${"*".repeat(k.length-2)}/`)

Замініть \tв коді буквальну вкладку.


3

Java, 185 184 167 152 байт

S->S.map(s->{s=s.replace("\t","    ");String t=s.replaceAll("^ +","");int n=s.length()-t.length();if(n>3){s="/";for(;n-->2;)s+="*";s+="/"+t;}return s;})

Враховуючи дуже вільне визначення рядкового масиву, що дається в початковому пості, я використовував, Stream<String>що дозволяє отримати певну економію байтів.

Для досягнення тієї ж мети я використовував різні методи, ніж РІ. Сам алгоритм досить однаковий.

Тестування та незагострення :

import java.util.Arrays;
import java.util.stream.Stream;

public class Main {

  public static void main(String[] args) {
    StringStreamTransformer sst = lines -> lines.map(line -> {
      line = line.replace("\t","    ");
      String trimmed = line.replaceAll("^ +", "");
      int startingSpaces = line.length() - trimmed.length();
      if (startingSpaces > 3) {
        line = "/";
        for(;startingSpaces > 2; startingSpaces--) {
          line += "*";
        }
        line += "/" + trimmed;
      }
      return line;
    });


    Stream<String> lines = Arrays.stream(new String[]{
      "lots of spaces and tabs after\t\t    \t\t         \t\t\t\t\t",
      "no space",
      " 1 space",
      "  2 spaces",
      "   3 spaces",
      "    4 spaces",
      "     5 spaces",
      "      6 spaces",
      "       7 spaces",
      "        8 spaces",
      "\t1 tab",
      "\t\t2 tabs",
      "\t\t\t3 tabs"
    });
    sst.map(lines).map(s -> s.replace(" ", ".").replace("\t","-")).forEach(System.out::println);


  }
}

2

Сітківка , 25 байт

\tПовинен бути замінений фактичним символом табуляції (0x09).

\t
4$* 
%`^  ( +)
/$.1$**/

Спробуйте в Інтернеті!

Пояснення

\t
4$* 

Замініть кожну вкладку на чотири пробіли.

%`^  ( +)
/$.1$**/

Перетворіть кожен рядок окремо ( %), зіставивши 2+Nпробіли на початку рядка та замінивши його на те, /.../де ...є Nкопії *.



2

СЕД (56 + 1 за -р) 57

s/⇥/    /g;tr;:r;s,^ ( *) ,/\1/,;T;:l;s,^(/\**) ,\1*,;tl

Де вкладка
1. замінює вкладки пробілами.
2. замінює перший і останній провідні місця на /.
3. замінює перший пробіл після /та 0+ *с а, *поки не буде збігу.


Оскільки sed задано, навколо коду не потрібні єдині лапки, як і видалення -r '' з інших відповідей sed, оскільки ви можете вважати, що сценарій зберігається у вихідному файлі, з яким ви працюєте -f. Будь-які додаткові прапори, такі як n або r, слід вважати кожним байтом. Таким чином, тут ви економите 2 байти.
seshoumara

Це я думав, але хочу впевнений. Спасибі.
Райлі

Команда ;after t також не потрібна. Що стосується самого коду, то вам потрібен ^ на початку третьої sкоманди, інакше такий вхід, як "3/5", перетворюється на "3 / * 5". У першій sкоманді у вас фактично є вкладка, але вона неправильно показана і вводить в оману, тому або використовуйте \ t, або вказуйте після, що char був вкладкою.
seshoumara

@seshoumara Спасибі, я намагаюся надсилати повідомлення зі свого телефону ... Це не найпростіше зробити.
Райлі

Я думаю, що я витратив більше часу на редагування цієї відповіді, ніж всі інші разом. Дякую за допомогу!
Райлі

1

Університет повинен розглянути можливість надання трохи більше місця для програм у Emacs Lisp (або за замовчуванням для tabifyта в untabifyпоодинці), оскільки вони отримують ще більше багатослівного, ніж Java. Слід також приділяти пильну увагу студентам (або викладачам), чий ідентифікаційний розмір менше чотирьох або які кодуються якоюсь мовою, що не схожа на С.

Наступне рішення має 206 байт

(lambda (b e)(let((tab-width 4))(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))))))

Припускаючи, що це tab-widthне потрібно чітко встановлювати, ми можемо зберегти 20 з них.

(lambda(b e)(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2))))))))

І неозорений варіант виглядав би так

(defun end-tab-war (beg end)
  (let ((tab-width 4))
    (untabify beg end)
    (goto-char beg)
    (while (re-search-forward "^ +" end t)
      (replace-match
       (format
        "/%s/"
        (apply 'concat
               (mapcar (lambda(x) "*")
                       (number-sequence 1
                                        (- (length (match-string 0))
                                           2)))))))))

Ми вперше untabifyв регіоні, перш ніж стрибнути до його початку. Потім, хоча ми бачимо пробіли на початку рядка, ми замінюємо його коментарем, який є таким, як зазначений пробіл. Якщо бути точним, коментар, який потрібно вставити, будує

 (format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))

який сам займає 97 байт. Коротше рішення скопіювати ряд рядків n разів високо цінується.


1

Ruby, 52 47 + 1 (p прапор) = 48 байт

Редагувати : збережено цілих 5 байтів, завдяки Ink Value Ink

ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'

1
Чи можете ви використовувати pпрапор, щоб скористатися тим, що (g) підміняє $_та змінює друковане значення? ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
Значення чорнила

Дякую, я не знав, що (g)subбез удару $_тут можна змінити .
michau

1

GNU sed, 66 64 + 1 (r прапор) = 65 байт

Редагувати: на 1 байт менше, завдяки пропозиції Райлі .

s/\t/    /g
s,^ ( *) ,/\1\n,
:
s,^(/\**) ( *\n),\1*\2,
t
s,\n,/,

Виконати: sed -rf formatter.sed input_file

Причина відокремлення \nпровідних пробілів від решти тексту на цьому рядку полягає в тому, що в іншому випадку рядок C ++, що починається з коментаря, подібного до цього /* */, перетвориться на /*****/простіший рядок 4, подібний s,^(/\**) ,\1*,чи парний s,^(/\**) ( */),\1*\2,. Оскільки sed виконує скрипт для кожного рядка \nвведення, в область шаблону при читанні не вводиться жодне .


Ви можете зберегти байт, не вводячи закриття, /поки ви не заміните \n. Це допоможе вам заощадити у рядку 4.
Райлі

@ Райлі Хороший улов. Оновлено код.
seshoumara

Можна зберегти інший, замінивши \tсимволом вкладки.
Райлі

@Riley Це правда, але оскільки він не буде надрукований як вкладка, я сумніваюся. Я буду пам’ятати про це, щоб майбутні відповіді sed з кількістю байтів були більш конкурентоспроможними.
seshoumara
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.