ASCII Книжные полки

27

Вы знаете те складные полки, которые в основном представляют собой деревянные ящики, которые можно сложить вместе? Мы собираемся смоделировать построение некоторых книжных полок из тех, что с искусством ASCII.

Все наши книги одинаково удобны по размеру и выглядят следующим образом:

|X|
|X|
|X|

Книжные полки представляют собой отдельные коробки, всегда по три символа высотой изнутри (достаточно для размещения книги в вертикальном положении), состоящие из |символов слева и справа, -символов сверху и снизу и достаточно широкие для размещения Xкниг (где Xвводится целое число). Например, вот книжная полка размера 3:

|---------|
|         |
|         |
|         |
|---------|

потому что вы можете вписать 3книги в него так

|---------|
||X||X||X||
||X||X||X||
||X||X||X||
|---------|

Входными данными будут два строго положительных целых числа, Xа Yгде Xширина имеющихся у нас полок (измеряется в книгах) и Yсколько книг нам нужно сложить. Если у нас больше книг, чем умещается на одной полке, нам нужно добавить больше полок сверху. Например, здесь ввод 4 wide / 6 books:

|------------|
||X||X|      |
||X||X|      |
||X||X|      |
|------------|
|------------|
||X||X||X||X||
||X||X||X||X||
||X||X||X||X||
|------------|

Если Y % X > 0, имея в виду, что количество книг не является целым числом, кратным размеру полки, остальные книги должны занимать самую верхнюю левую позицию (как в случае с 4 6выше), а оставшаяся часть этой полки заполняется пространства.

вход

  • Два строго положительных целых числа в любом удобном формате , каждое >0.
  • Вы можете использовать входные данные в любом порядке (например, сначала размер полок, затем количество книг или наоборот). Пожалуйста, укажите в заявке порядок ввода.
  • Вы можете смело предположить, что ни один из входных данных не будет больше размера вашего языка по умолчанию [int](или эквивалентного).

Выход

В результате ASCII художественное представление книг и книжных полок.

правила

  • Начальные или завершающие символы новой строки или пробелы являются необязательными, при условии, что сами символы выстроены правильно.
  • Допустимы либо полная программа, либо функция. Если функция, вы можете вернуть вывод, а не распечатать его.
  • Если возможно, укажите ссылку на среду онлайн-тестирования, чтобы другие люди могли опробовать ваш код!
  • Стандартные лазейки запрещены.
  • Это поэтому применяются все обычные правила игры в гольф, и выигрывает самый короткий код (в байтах).

Дальнейшие примеры

6 wide / 2 books
|------------------|
||X||X|            |
||X||X|            |
||X||X|            |
|------------------|

2 wide / 6 books
|------|
||X||X||
||X||X||
||X||X||
|------|
|------|
||X||X||
||X||X||
||X||X||
|------|
|------|
||X||X||
||X||X||
||X||X||
|------|

4 wide / 9 books
|------------|
||X|         |
||X|         |
||X|         |
|------------|
|------------|
||X||X||X||X||
||X||X||X||X||
||X||X||X||X||
|------------|
|------------|
||X||X||X||X||
||X||X||X||X||
||X||X||X||X||
|------------|
AdmBorkBork
источник
Можно ли сделать так, чтобы полка с наименьшим количеством книг
Золотое
1
@GoldenRatio Нет, книги должны быть заполнены снизу вверх, слева направо.
AdmBorkBork

Ответы:

14

JavaScript (ES6), 100 99 98 байт

Принимает ширину wи количество книг bв карри синтаксисе (w)(b).

w=>g=(b,s=`|${'-'.repeat(w*3)}|
`,r=s.replace(/---/g,_=>b&&b--?'|X|':'   '))=>(b?g(b)+s:s)+r+r+r+s

Отформатировано и прокомментировано

w =>                                // main function: takes width 'w' as input, returns 'g'
  g = (                             // g = recursive function with:
    b,                              //   - b = number of books
    s = `|${'-'.repeat(w * 3)}|\n`, //   - s = top/bottom of shell, filled with '-'
    r = s.replace(                  //   - r = pattern of the current row of books,
      RegExp('---', 'g'),           //         using 's' as a template and updating
      _ => b && b-- ? '|X|' : '   ' //         'b' while building it
    )                               // NB: 'r' must be defined in the scope of 'g',
  ) =>                              //     otherwise it would be overwritten by
    (                               //     subsequent calls
      b ?                           // if there are remaining books:
        g(b) + s                    //   do a recursive call and append shell top
      :                             // else:
        s                           //   just append shell top
    ) + r + r + r + s               // append book rows and shell bottom

Контрольные примеры

Arnauld
источник
9

Баш (+ коммунальные услуги), 130, 108, 106 байт

Единый непрерывный конвейер оболочки для отображения ваших книжных полок.

Changelog:

  • Оптимизировано первое выражение sed, -12 байт (Thx @Riley!)
  • Заменяется printf + seqна сырой printf, -10 байт
  • Рефакторинг второго выражения sed, -2 байта

Golfed

printf %$2s\\n|fold -$1|sed "s/ /|X|/g;:;/.\{$[$1*3]\}/!s/$/ /;t;h;s/./-/gp;x;p;p;p;x"|sed 's/.*/|&|/'|tac

$./shelf 6 8
|------------------|
||X||X|            |
||X||X|            |
||X||X|            |
|------------------|
|------------------|
||X||X||X||X||X||X||
||X||X||X||X||X||X||
||X||X||X||X||X||X||
|------------------|

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

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

$./shelf 2 3

printf %$2s\\n- сгенерировать n пробельных символов, по одному на книгу (показано как _)

___

fold -$1 - сложить их по длине полки

__
_

sed "s/ /|X|/g;"- заменить _на X, добавить обложки книг

|X||X|
|X|

:;/.\{$[$1*3]\}/!s/$/ /;t- правая панель с пробелами (показана как _)

|X||X|
|X|___

h;s/./-/gp;x;p;p;p;x- утроить каждую строку и добавить ---до и после нее.

------
|X||X|
|X||X|
|X||X|
------
------
|X|   
|X|   
|X|   
------

sed 's/.*/|&|/'|tac- перенос строк в | |обратном порядке с так

|------|
||X|   |
||X|   |
||X|   |
|------|
|------|
||X||X||
||X||X||
||X||X||
|------|
дирижабль
источник
В первом sed вы можете использовать безымянный ярлык, и tвместо него bвам не понадобится {}. Вы можете пропустить, s/./-/gпотому что они уже -с. Попробуйте онлайн!
Райли
@Riley Это отличный совет, спасибо!
Цеппелин
6

Python 2 133 113 105 байт

Я уверен, что есть лучший способ ...

X,Y=input()
k='|'+'---'*X+'|'
while Y:g=Y%X or X;print k+'\n'+('|'+'|X|'*g+'   '*(X-g)+'|'+'\n')*3+k;Y-=g

Ввод принят width, books

-20 байт, спасибо @ovs за то, что он заметил ненужную лямбда-функцию!
-8 байт, спасибо @ovs за сокращение ввода.

HyperNeutrino
источник
X,Y=input()это более короткий способ принять значения.
овс
@ovs Ой, подожди, я положил это туда с первой попытки. Упс. Хороший улов, спасибо!
HyperNeutrino
1
@ovs Спасибо, так что тогда ввод принимается как X, Y, верно?
HyperNeutrino
2
Я думаю, что вы можете сохранить два байта, определив '|'в качестве переменной.
Орджан Йохансен
6

Пакетный, 261 байт

@set/an=~-%1%%%2+1,b=%1-n
@set s=
@set t=
@for /l %%i in (1,1,%2)do @call set t=---%%t%%&if %%i gtr %n% (call set s=%%s%%   )else call set s=%%s%%X
@for %%s in ("|%t%|" "|%s:X=|X|%|" "|%s:X=|X|%|" "|%s:X=|X|%|" "|%t%|")do @echo %%~s
@if %b% gtr 0 %0 %b% %2

Использую мой трюк из моего Пакетного ответа « Давайте играть в теннис», чтобы легко печатать множество |символов.

Нил
источник
5

Haskell , 100 байт

x#yвозвращает строку для ширины xи yкниг.

s?n=[1..n]>>s
x#y|x<y=x#(y-x)++x#x|w<-"---"?x,b<-"|X|"?y++"   "?(x-y)=[w,b,b,b,w]>>=('|':).(++"|\n")

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

Основная функция / оператор есть #. Когда x<yон разбивает книги на y-xи x, а затем рекурсивно. Когда x>=y, wи bявляются два типа линии, минус внешние |s и символ новой строки.

Вспомогательный оператор s?nобъединяет nкопии строки s.

Орджан Йохансен
источник
5

PowerShell , 149 134 байта

param($w,$b)$s="|$('-'*$w*3)|"
if($a=$b%$w){,$s+,"|$('|X|'*$a)$(' '*3*($w-$a))|"*3+$s}
if($b-=$a){(,$s+,"|$('|X|'*$w)|"*3+$s)*($b/$w)}

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

Принимает $width и $books. Устанавливает строку $sкак одну из горизонтальных полок. Тогда у нас есть два ifутверждения.

Первый проверяет, есть ли у нас «остатки» книг. Если это так, мы выводим полку, (количество книг плюс количество пробелов) *3и другую полку.

Далее мы видим, остались ли у нас книги после удаления остатков ( $a). Такая же настройка, за исключением того, что мы используем $wколичество книг. Поскольку в этот момент $bгарантируется кратность $w(поскольку мы удалили остаток $a), нам не нужно беспокоиться о округлении.

Убрал [math]::Floor()звонок, сэкономив 15 байт

Все эти строки остаются в конвейере, и неявное Write-Outputпроисходит при завершении программы.

AdmBorkBork
источник
4

CJam , 62 61 байт

q~1a*W$/W$f{0e]}{{"|X|"S3*?}%s__'-3*W$*_}%1m>W%"|
|"*"||"\*o;

Принимает вход как width books

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

объяснение

q~           Read and eval input (pushes width W and books B to the stack)
1a*          Push an array containing  the number 1 B times
W$/          Split it into chunks of size W
W$f{0e]}     Pad each chunk to width W by adding 0's to the right (the last chunk might be 
              shorter than W)
{            Apply the following to each chunk:
 {            Apply the following to each number in the chunk:
  "|X|"S3*?    Push "|X|" if the number is 1, or "   " if it's 0
 }%           (end of block)
 s            Stringify (joins with no separator)
 __           Duplicate twice (each shelf is 3 identical lines)
 '-3*W$*_     Push a string containing '-' repeated 3×W times, then duplicate it
}%           (end of block)
              At this point we have an array containing sequences of 3 identical lines 
              each followed by two lines of -'s
1m>          Rotate the array 1 to the right; brings the final line of -'s to the start
W%           Reverse the array, so that the top shelf is the partially empty one
"|\n|"*      Join the array with the string "|\n|", to build the sides of the shelves
"||"\*       Join the string "||" with the shelf string (adds the first and last | chars)
o            Print the result
;            Pop and discard W
Бизнес Кот
источник
4

Python 3, 142 байта

Все еще работаю над этим. bдля «количества книг» и wдля ширины полки.

def s(b,w):
 R=b%w
 B='|\n'
 I='|'
 X='|X|'
 d=I+3*w*'-'+B
 f=I+X*w+B
 p=I+R*X+3*(w-R)*' '+B
 print(R and d+3*p+d or" ")+b//w*(d+3*f+d))
Хуан Мелейро
источник
Добро пожаловать в PPCG! Это не работает для меня, если R=b%wне перейти к следующей строке. Кроме того, вы должны иметь возможность удалить пробелы вокруг этих трех, =чтобы сохранить несколько байтов.
Бизнес Кот
Добро пожаловать в PPCG!
AdmBorkBork
Вы можете заменить d+3*p+d if R!=0 else ''наR and d+3*p+d or''
shooqie
@shooqie Мне любопытно, как это может оценить результат d+3*p+d?
Хуан Мелейро
1
Вы можете сохранить несколько байтов, поместив все определения в одну строку, используя точки с запятой.
L3viathan
3

AHK, 208 байтов

AutoTrim,Off
w=%1%
b=%2%
f:=Mod(b,w)
Loop,%w%
s=%s%---
s=|%s%|`n
If (f>0) {
Loop,%f%
t=%t%|X|
Loop,% w-f
t=%t% ` ` `
t=|%t%|`n
t:=s t t t s
}
Loop,%w%
r=%r%|X|
r=|%r%|`n
Loop,% (b-f)/w
t:=t s r r r s
Send,%t%

Есть несколько вещей, которые мешают мне играть в гольф дальше:

  • AutoHotkey не имеет встроенной функции повтора
  • Вы не можете напрямую использовать переданные в аргументах ( %1%& %2%) в математических функциях, потому что они ожидают ввода переменной или числа, и он будет считать неоткрытый 1номер первым, а не имя переменной
  • Я не очень хорош в гольфе

Более легкая для чтения версия выше выглядит следующим образом:

AutoTrim,Off
w=%1%
b=%2%
f:=Mod(b,w)

Loop,%w%
   s=%s%---
s=|%s%|`n

If (f>0) {
   Loop,%f%
      t=%t%|X|
   Loop,% w-f
      t=%t% ` ` `
   t=|%t%|`n
   t:=s t t t s
}

Loop,%w%
   r=%r%|X|
r=|%r%|`n

Loop,% (b-f)/w
   t:=t s r r r s

Send,%t%

Если a Loopне использует скобки {}, то только следующая строка является частью цикла. Если :=вместо переменной установить значение переменной =, вы можете удалить escape-символы знака процента. Тильда n - символ новой строки.

Инженер Тост
источник
3

Java 7, 230 224 222 байта

String c(int w,int b){String r="",n="|\n",z="|";int i=0,j,k,t=b%w<1?w:b%w,x=b/w+(t!=w?1:0);for(;i++<w;z+="---");z+=n;for(i=0;i<x;i++){r+=z;for(j=0;j++<3;r+=n){r+="|";for(k=0;k<w;r+=i<1&k++>=t?"   ":"|X|");}r+=z;}return r;}

Объяснение:

String c(int w, int b){                // Method with two integer parameters and String return-type
  String r = "",                       //  The return-String
         n = "|\n",                    //  Part that's used multiple times in the code
         z = "|";                      //  Shelf part of the book-boxes
  int i = 0, j, k,                     //  Indexes used in the for-loops
      t = b%w < 1 ? w : b%w,           //  Books on top shelf
      x = b/w + (t != w ? 1 : 0);      //  Amount of shelves
  for(; i++ < w; z += "---"); z += n;  //  Create the shelf-part ("|---|"; with w times "---")
  for(i = 0; i < x; i++){              //  Loop over the rows
    r += z;                            //   Append the result with the shelf-part
    for(j = 0; j++ < 3; ){             //   Loop three times (the height of the books & boxes)
      r += "|";                        //    Append the result-String with "|"
      for(k = 0; k < w;                //    Loop over the columns
          r +=                         //     And append the result-String with:
           i < 1                       //      If this is the first row:
           & k++ >= t ?                //      And the current column is larger or equal to the amount of books in the top shelf
             "   "                     //       Use an empty space
           :                           //      Else:
             "|X|"                     //       Use the book-part
            );                         //    End of columns loop
         r += n;                       //    Append the result-String with a "|" and a new-line
       }                               //   End of the loop of three
      r += z;                          //   Append the result-String with the shelf-part
    }                                  //  End of rows loop
    return r;                          //  Return the result-String
 }                                     // End of method

Тестовый код:

Попробуй это здесь.

class M{
  static String c(int w,int b){String r="",n="|\n",z="|";int i=0,j,k,t=b%w<1?w:b%w,x=b/w+(t!=w?1:0);for(;i++<w;z+="---");z+=n;for(i=0;i<x;i++){r+=z;for(j=0;j++<3;r+=n){r+="|";for(k=0;k<w;r+=i<1&k++>=t?"   ":"|X|");}r+=z;}return r;}

  public static void main(String[] a){
    System.out.println(c(6, 2));
    System.out.println(c(2, 6));
    System.out.println(c(4, 9));
  }
}

Выход:

|------------------|
||X||X|            |
||X||X|            |
||X||X|            |
|------------------|

|------|
||X||X||
||X||X||
||X||X||
|------|
|------|
||X||X||
||X||X||
||X||X||
|------|
|------|
||X||X||
||X||X||
||X||X||
|------|

|------------|
||X|         |
||X|         |
||X|         |
|------------|
|------------|
||X||X||X||X||
||X||X||X||X||
||X||X||X||X||
|------------|
|------------|
||X||X||X||X||
||X||X||X||X||
||X||X||X||X||
|------------|
Кевин Круйссен
источник
1
Я не знаю как, но похоже, что лямбды .repeatдействительно помогают в этом вызове .
Оливье Грегуар
@ OlivierGrégoire Учитывая, что я опубликовал это около 1,5 года назад, я не удивлен, что это может быть достаточно существенно. ;)
Кевин Круйссен
Оу ... Я не проверил дату: я только увидел, что этот вопрос активен и что возможен полностью другой алгоритм для Java. Мой плохой ...
Оливье Грегуар
@ OlivierGrégoire Нет проблем, и хорошо с вашим ответом. :) Я почти испытываю ностальгию, оглядываясь на этот ответ, когда я все еще добавлял тестовые примеры и выводил в ответ и отвечал на все вопросы в Java 7, потому что я еще не понимал Java 8. XD
Кевин Круйссен
2

PowerShell, 109 байт

param($w,$b)for(;$b;$b-=$c){if(!($c=$b%$w)){$c=$w}($l="|$('-'*$w*3)|")
,"|$('|X|'*$c)$(' '*($w-$c)*3)|"*3
$l}

Менее гольф тестовый скрипт:

$f = {

param($w,$b)
for(;$b;$b-=$c){
    if(!($c=$b%$w)){$c=$w}
    ($l="|$('-'*$w*3)|")
    ,"|$('|X|'*$c)$(' '*($w-$c)*3)|"*3
    $l
}

}

@(
    ,(6, 2, 
    "|------------------|",
    "||X||X|            |",
    "||X||X|            |",
    "||X||X|            |",
    "|------------------|")

    ,(2, 6,
    "|------|",
    "||X||X||",
    "||X||X||",
    "||X||X||",
    "|------|",
    "|------|",
    "||X||X||",
    "||X||X||",
    "||X||X||",
    "|------|",
    "|------|",
    "||X||X||",
    "||X||X||",
    "||X||X||",
    "|------|")

    ,(4, 9,
    "|------------|",
    "||X|         |",
    "||X|         |",
    "||X|         |",
    "|------------|",
    "|------------|",
    "||X||X||X||X||",
    "||X||X||X||X||",
    "||X||X||X||X||",
    "|------------|",
    "|------------|",
    "||X||X||X||X||",
    "||X||X||X||X||",
    "||X||X||X||X||",
    "|------------|")
) | % {
    $w,$b,$expected = $_
    $result = &$f $w $b
    "$result"-eq"$expected"
    $result
}

Выход:

True
|------------------|
||X||X|            |
||X||X|            |
||X||X|            |
|------------------|
True
|------|
||X||X||
||X||X||
||X||X||
|------|
|------|
||X||X||
||X||X||
||X||X||
|------|
|------|
||X||X||
||X||X||
||X||X||
|------|
True
|------------|
||X|         |
||X|         |
||X|         |
|------------|
|------------|
||X||X||X||X||
||X||X||X||X||
||X||X||X||X||
|------------|
|------------|
||X||X||X||X||
||X||X||X||X||
||X||X||X||X||
|------------|

PowerShell, 109 байт, альтернатива

param($w,$b)for(;$b;$b-=$c){($l="|$('---'*$w)|")
,"|$('|X|'*($c=(($b%$w),$w-ne0)[0]))$('   '*($w-$c))|"*3
$l}
Mazzy
источник
1

Python 2 , 120 118 байт

i,j=input()
a=j%i
n='|\n'
x='|'+'---'*i+n
print(x+('|'+'|x|'*a+' '*(i-a)*3+n)*3,'')[a<1]+(x+('|'+'|x|'*i+n)*3)*(j/i)+x

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

В течение последних нескольких дней хотел попробовать это. Теперь, когда у меня наконец есть время сделать это, есть уже более короткий ответ Python. Ну да ладно, просто выложили как альтернативу.

Ввод за ширину, книги

ElPedro
источник
1

SOGL , 64 байта

be%→M"Q└ƨS‘*ač;┼→S%‘A |e3* -* |++M?tMSeM-9*@*a+┼Ot}be÷:?{teSa┼Ot

Пояснение: Первая функция:

   →M  define function M which pushes
b      the book amount
  %    mod
 e     the bookshelf width

вторая функция:

           →S  create function S (example input: 3)          [3]
"Q└ƨS‘         push the string "|||XXX|||" (the book)        [3, "|||XXX|||"]
      *        multiply by the number on stack (book count)  ["|||XXX||||||XXX||||||XXX|||"]
       a       push variable A (later defined "|||")         ["|||XXX||||||XXX||||||XXX|||", "|||"]
        č      chop into char array                          ["|||XXX||||||XXX||||||XXX|||", ["|", "|", "|"]]
         ;     swap top 2 on stack                           [["|", "|", "|"], "|||XXX||||||XXX||||||XXX|||"]
          ┼    horizontally append                           [["||X||X||X|", "||X||X||X|", "||X||X||X|"]]

эта функция ожидает число (количество книг) в стеке и выводит книги книжных полок

["||X||X||X|",
 "||X||X||X|",
 "||X||X||X|"]

Далее приведен пример, где e = 3 (ширина книжной полки) и b = 8 (количество книг)

%‘A              var A = "|||"                        
    |            push "|"                      ["|"]                
     e3*         push E * 3                    ["|", 9]             
         -*      push that many "-"es          ["|", "---------"]   
            |+   append "|"                    ["|", "---------|"]  
              +  prepend the "|"               ["|---------|"]      

это верхняя / нижняя строка книжной полки и всегда остается в первой части стека (полупустая книжная полка)

Первая основная часть

M?               }               if the modulo != 0
  tM                             output the bookshelf top/bottom line
    S                            execute the S function width the modulo
     eM-                         push bookshelf width - modulo (empty space count)
        9*                       multiply by 9 (books are 3x3 so 3x3 spaces)
          @*                     get that many spaces
            a+                   append to that "|||"
              ┼                  horizontally append
               O                 output
                t                output the bookshelf top/bottom line

И последняя часть

be÷            floor divide book amout by width (full shelves)
   :?          if not 0 (a bug makes all loops execute once)
     {         repeat
      t        output the bookshelf top/bottom line
       eS      execute S with shelf width (full shelf)
         a┼    horizontally append "|||"
           O   output
            t  output the bookshelf top/bottom line
dzaima
источник
0

PHP> = 7.1, 138 байт

for([,$w,$b]=$argv;$i<ceil($b/$w)*5;)echo str_pad("|".str_repeat(["","|X|"][$t=($i+1)%5>1],$i++<5&&$b%$w?$b%$w:$w),$w*3+1,"- "[$t])."|\n";

Онлайн версия

Йорг Хюльсерманн
источник
0

Холст , 33 байта

|X|3*×⁷3×⇵-×|3*×╫│;22╋P
%?%⁸}÷[⁷⁸

Попробуй это здесь!

Пояснение (некоторые символы были заменены, чтобы выглядеть более моноширинно):

|X|3*×⁷3×⇵-×|3*×╫│;22╋P  helper function. Prints a shelf with X books
|X|                      push "|X|"
   3*                    repeat it 3 times vertically
     ×                   repeat that horizontally by the item (X) below on the stack
      ⁷3×                push width * 3
         ⇵               ceiling divide that by 2
          -×             repeat "-" that many times
            |3*          repeat "|" vertically 3 times (aka "|¶|¶|")
               ×         prepend that to the dashes (aka ¼ of a bookshelf)
                ╫│       quad-palindromize with horizontal overlap of the remainder
                           taken before and vertical overlap of 1
                  ;      get the books on top
                   22╋   and at coordinates (2;2) in the shelf, place them in
                      P  print that whole thing

%?%⁸}÷[⁷⁸  
%?  }      if width%amount (!= 0)
  %⁸         execute the helper function with width%amount on the stack
     ÷[    repeat floor(width/amount) times
       ⁷     push width
        ⁸    execute the helper function
dzaima
источник
0

Пип -n , 45 байт

Wb-:yPPZ['-X3Xa"|X|"X(Yb%a|a).sX3Xa-yRL3]WR'|

Принимает ширину и количество книг, соответственно, в качестве аргументов командной строки. Попробуйте онлайн!

объяснение

Мы запускаем цикл, чтобы напечатать полки одну за другой сверху вниз. На каждой итерации мы обновляем b(количество книг для печати), вычитая y(количество книг, напечатанных на этой итерации). Когда bдостигает 0, цикл выходит.

Wb-:yPPZ['-X3Xa"|X|"X(Yb%a|a).sX3Xa-yRL3]WR'|
                                               a is 1st cmdline arg (shelf width); b is 2nd cmdline
                                                 arg (# books); s is space; y is ""
                                               Note that "" becomes zero in numeric contexts
Wb-:y                                          While b decremented by y is nonzero:
                       b%a|a                    b mod a, or a if that quantity is zero
                      Y                         Yank that value into y
                     (      )                   This is the number of books on the current shelf
               "|X|"                            Book-spine string
                    X                           Repeated y times
                                  a-y           Number of empty slots on the current shelf
                              sX3X              Three spaces for each slot
                             .                  Concatenate to the book-spines string
                                     RL3        Make a list of 3 copies of that string
         '-X3Xa                                 3*a hyphens
        [                               ]       Put that string and the above list in a list
                                         WR'|   Wrap all strings in the nested list in |
      PZ                                        Palindromize the outer list (adding a copy of the
                                                hyphens to the end of it)
     P                                          Print, joining all sublists on newlines (-n flag)

Поскольку это немного запутано, вот пример первой итерации, когда a = 3, b = 8:

Yb%a|a       2
"|X|"X ^     "|X||X|"
^ .sX3Xa-y   "|X||X|   "
^ RL3        ["|X||X|   ";"|X||X|   ";"|X||X|   "]
['-X3Xa ^ ]  ["---------";["|X||X|   ";"|X||X|   ";"|X||X|   "]]
^ WR'|       ["|---------|";["||X||X|   |";"||X||X|   |";"||X||X|   |"]]
PZ ^         ["|---------|";["||X||X|   |";"||X||X|   |";"||X||X|   |"];"|---------|"]

который затем печатает как

|---------|
||X||X|   |
||X||X|   |
||X||X|   |
|---------|
DLosc
источник
0

Pyth , 56 байт

M++GHGV_fTs*V,]Q1.DEQjCg*5\|smgL\-*L3?d"|X|""   ".[*]1N0

Принимает ширину полки, количество книг в качестве отдельных аргументов в этом порядке. Попробуйте онлайн здесь или проверьте все тестовые примеры сразу здесь .

M++GHGV_fTs*V,]Q1.DEQjCg*5\|smgL\-*L3?d"|X|""   ".[*]1N0Q   Implicit: Q=1st arg, E=2nd arg
                                                            Trailing Q inferred
M                                                           Define a function, g(G,H):
 ++GHG                                                        Return G + H + G
                 .DEQ                                       Divmod E by Q, yields [E//Q, E%Q]
             ,]Q1                                           [[Q], 1]
           *V                                               Vectorised multiply the two previous results
                                                              This yields Q repeated E//Q times, then E%Q
          s                                                 Flatten
        fT                                                  Filter out falsey values (i.e. trailing 0 if present)
       _                                                    Reverse (to put partially filled shelf on top)
      V                                                     For N in the above:
                                                    ]1        [1]
                                                   *  N       Repeat the above N times
                                                 .[    0Q     Pad the above on the right with 0, to length Q
                             m                                Map the above, as d, using:
                                     ?d"|X|""   "               If d != 0, yield "|X|", else "   "
                                  *L3                           Multiply each char by 3
                                                                  Yields ['|||','XXX','|||'] or ['   ','   ','   ']
                              gL\-                              Use g to wrap each element in '-'
                            s                                 Flatten
                       g*5\|                                  Use g to add '|||||' to start and end of the above
                      C                                       Transpose
                     j                                        Join on newlines, implicit print
Sok
источник
0

Далее , 622 байта (свернуто (убрать комментарии, отступы, имена из 1 символа) до 303 байтов)

Моя первая игра с Forth :)

: bar 124 EMIT ;

: delimline ( width -- )
    bar
    3 * 0 DO 45 EMIT LOOP
    bar CR
;

: bookline ( width books -- )
    bar
    DUP 0 DO bar 88 EMIT bar LOOP
    2DUP = IF
        DROP DROP
    ELSE
        - 0 do 3 SPACES LOOP
    THEN
    bar CR
;

: shelf ( width books -- )
    DUP 0 = IF
        DROP DROP
    ELSE
        OVER delimline
        3 0 DO OVER OVER bookline LOOP
        DROP delimline
    THEN
;

: stack ( width books -- )
    CR
    OVER OVER OVER MOD shelf
    OVER /
    DUP 0 = IF
        DROP DROP
    ELSE 
        0 DO DUP DUP shelf LOOP
    THEN
;

6 2 stack
2 6 stack
3 5 stack
4 4 stack

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

Выход

| ------------------ |
|| X || X | |
|| X || X | |
|| X || X | |
| ------------------ |

| ------ |
|| X || X ||
|| X || X ||
|| X || X ||
| ------ |
| ------ |
|| X || X ||
|| X || X ||
|| X || X ||
| ------ |
| ------ |
|| X || X ||
|| X || X ||
|| X || X ||
| ------ |

| --------- |
|| X || X | |
|| X || X | |
|| X || X | |
| --------- |
| --------- |
|| X || X || X ||
|| X || X || X ||
|| X || X || X ||
| --------- |

| ------------ |
|| X || X || X || X ||
|| X || X || X || X ||
|| X || X || X || X ||
| ------------ |
PMG
источник