ASCII Водопровод


19

вступление

Рассмотрим сетку символов, f A\/таких как

f  f  f  
      A  
   A / \ 
\ /     A
    A \/ 
   /     
 \/         

где:

  • f представляет собой кран, который льет поток воды вниз
  • A разветвляется поток воды выше, так что ровно половина идет влево, а ровно половина идет вправо
  • \ смещает поток воды вверх вправо на одну единицу
  • / смещает поток воды выше на одну единицу
  • комбинации \/создают желоб с бесконечной емкостью, который собирает потоки воды над ним
  • [space] пустое пространство, через которое вода может пройти

Исходя из этого, мы можем представить себе путь, по *которому будет идти water ( ), когда он выходит из смесителей и падает либо в желоба, либо из области сетки:

f  f  f    <-- first second and third faucets
*  * *A* 
* *A*/ \*
\*/ *  *A  <-- a '*' is not drawn to the right of this A because it would be out of the 9×7 bounds
 * *A*\/   <-- upper trough
 **/ *   
 \/  *     <-- lower trough

Предполагая, что 3 крана выводят одинаковое количество воды по одному, мы видим, что

  • Вся вода первого крана поступает в нижний желоб.
  • Одна половина воды второго крана поступает в нижний желоб, а другая половина делится между нижним желобом и падает с решетки.
  • Одна четверть воды третьего крана поступает в нижнюю впадину, одна четверть падает с нижней части решетки, одна четверть попадает в верхнюю впадину, а одна четверть падает с решетки вправо.

Отсюда можно сказать, что (1 + 3/4 + 1/4 + 1/4) / 3 = 75%вода попадает в кормушки и (1/4 + 1/4 + 1/4) / 3 = 25%падает с сетки.

проблемы

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

Задача 1
Напишите программу, которая выводит долю воды, которая течет в впадины для данной сетки. Выход из приведенного выше примера будет просто 0.75.

Задача 2
Напишите программу, которая, учитывая сетку, рисует *в местах, где течет вода, как я делал выше. Вы не должны перезаписывать ничего, кроме пробелов, и сетка не должна изменять размер. Так что для чего-то вроде

 f
/A

ничего не нужно делать, поскольку, хотя вода течет по обе стороны от А, ее нельзя нарисовать влево, не удалив, /и нельзя нарисовать вправо, не увеличив размер сетки 2 × 2.

Задача 3 (обновлено)
Напишите программу, которая принимает два неотрицательных целых числа, общее количество T и сумму, которую нужно сохранить K (T> = K). Создайте и нарисуйте сетку с ровно одной fтакой, чтобы, когда этот кран изливал Т единиц воды, точно K попадет в желоба. Если это невозможно сделать в конечной сетке для конкретной пары (T, K), выведите «Impossible».

Разъяснения (применимо ко всем задачам)

  • Ввод может быть через стандартный ввод, или файл, или даже вызов функции для строкового представления сетки. Просто сделайте очевидным, как запустить разные входы.
  • Выход должен идти в стандартный вывод.
  • \Aа A/и AAтакже впадины , как и следовало ожидать.
  • Сетка w на h всегда будет хорошо отформатированным прямоугольником с символами w * h без учета перевода строки. Не будет пропущенных пробелов и вхождений *.
  • Размеры сетки могут быть как 1 × 1, так и произвольно большими. (Произвольно большой в пределах разумного, int.maxValue или тому подобное является приемлемым пределом. То же самое касается T и K.)
  • Поток выше потока fтечет прямо через него.
  • Смесители могут быть где угодно, а не только в верхнем ряду.
  • A всегда делит количество налитой на него воды ровно пополам.

Примечание: такие вещи, как /Aи //являются совершенно действительными. Вода делает свободно перетекать между символами (хотя для задачи 2 там не хватает места , чтобы сделать это).

Итак, в настройках

ff

/A

Левый fпоток льется вниз, ударяется /и смещается влево. Правый fпоток льется вниз, ударяется о A, половина идет вправо, а половина идет влево между Aи /.

например

 ff
 **
*/A*
** *
** *

3
+1 Отличный вызов. Что касается задачи 3, то решетка сверху не будет верным ответом, потому что она имеет 3 fс
edc65

@ edc65 Ах, хороший улов!
Увлечения Келвина


2
Для второй задачи вам нужно указать, как обрабатывать ввод, например, /Aесли вода падает на A. Для всех проблем было бы хорошо уточнить, \Aявляется ли корыто. Для третьего вызова следует Aли предположить , что 3 падающие на единицу единицы делятся 1.5 / 1.5(так что на самом деле вход представляет собой одно рациональное число) или это так 2 / 1, и в каком случае какая сторона получает 2?
Питер Тейлор

1
@PeterTaylor Спасибо. Я прояснил эти моменты. Я предполагаю, что T и K могут быть числами с плавающей точкой, но я сохраняю их целыми числами для простоты. (Но если T = 3 действительно ударит, Aто обе стороны получат 1,5. Это зависит от кодера, чтобы убедиться, что точность с плавающей точкой не является проблемой.)
Хобби Calvin's

Ответы:


3

Все испытания C # 690 байт (416 байт + 274 байт)

Задачи 1 и 2 C # 579 446 416 байт

Это полная программа, которая должна выполнить задачи 1 и 2, примерно. Он читает строки ввода из стандартного ввода, пока не получит пустую строку. Он выводит результат для Challenge 2, а затем результат для Challenge 1. Использует десятичный класс .NET, чтобы избежать ошибок округления.

using C=System.Console;class P{static void Main(){decimal u,t=0,f=0;string c,z="";for(decimal[]n=null,o;(c=C.ReadLine())!="";z+='\n'){int s=c.Length,i=s,e;o=n;n=new decimal[s];for(o=o??n;i-->0;n[i]+=(e&2)*u/2){e=c[i]%13;u=o[i]/(e<1?2:1);if(e%8<1)if(i>0)if(c[i-1]%7<3)t+=u;else n[i-1]+=u;if(e<2)if(i<s-1)if(c[i+1]%2>0)t+=u;else n[i+1]+=u;if(e>9){u++;f++;}}for(;++i<s;)z+=c[i]<33&n[i]>0?'*':c[i];}C.WriteLine(z+t/f);}}

Менее гольф:

using C=System.Console;
class P
{
    static void Main()
    {
        decimal u,t=0,f=0;
        string c,z="";

        for(decimal[]n=null,o;(c=C.ReadLine())!="";z+='\n')
        {
            int s=c.Length,i=s,e;
            o=n;
            n=new decimal[s];
            for(o=o??n;i-->0;n[i]+=(e&2)*u/2)
            {
                e=c[i]%13;
                u=o[i]/(e<1?2:1);

                if(e%8<1)
                    if(i>0)
                        if(c[i-1]%7<3)t+=u;
                        else n[i-1]+=u;
                if(e<2)
                    if(i<s-1)
                        if(c[i+1]%2>0)t+=u;
                        else n[i+1]+=u;
                if(e>9)
                {
                    u++;
                    f++;
                }
            }
            for(;++i<s;)
                z+=c[i]<33&n[i]>0?'*':c[i];
        }

        C.WriteLine(z+t/f);
    }
}

Тестовый прогон (с отсутствием пробелов, которые, я обещаю, есть):

f  f  f
      A
   A / \
\ /     A
    A \/
   /
 \/

f  f  f
*  * *A*
* *A*/ \*
\*/ *  *A
 * *A*\/
 **/ *
 \/  *
0.75

Задача 3 C # 274 байта

Это полная программа, которая должна завершить задачу 3. Мне удалось сэкономить 6 байтов, написав свой собственный целочисленный синтаксический анализатор для чтения входных данных вместо того, чтобы Splitиспользовать ReadLineи использовать long.Parse;

using C=System.Console;class P{static void Main(){long t=-1,f=t,k;for(;f<0;)for(f=t,t=0;(k=C.Read())>47;)t=t*10+k-48;var r="Impossible\n";for(k=t;k<t*f;)k*=2;if(f<1||(k/f)*f==k)for(r=" f \n";t>0&t<f;t-=(t/f)*f)r+=((t*=2)<f?" ":"A")+"A \n/ /\n";C.Write(r+(t<f?"":"AAA\n"));}}

Менее гольф:

using C=System.Console;
class P
{
    static void Main()
    {
        long t=-1,f=t,k;
        for(;f<0;)
            for(f=t,t=0;(k=C.Read())>47;)
                t=t*10+k-48;

        var r="Impossible\n";
        for(k=t;k<t*f;)
            k*=2;
        if(f<1||(k/f)*f==k)
            for(r=" f \n";t>0&t<f;t-=(t/f)*f)
                r+=((t*=2)<f?" ":"A")+"A \n/ /\n";
        C.Write(r+(t<f?"":"AAA\n"));
    }
}

Тестовый прогон (опять же с отсутствием пробелов, которые, я обещаю, есть):

32 17
 f
AA
/ /
 A
/ /
 A
/ /
 A
/ /
AA
/ /

3

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

  • Каково поведение /A(вода течет по A), //(вода течет по правой стороне) и вариации этого принципа? Вода течет к первому «свободному месту» сбоку или течет «ниже» своего соседа?

Просто попробуйте, это может быть упрощено (что я сделаю позже, отредактировав этот пост).

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

Javascript, 226 байт (Задача 1)

function f(c){function h(b,a,d,e){b<c.length&&0<=a&&a<c[0].length&&("\\"==c[b][a]?"/"==e||"A"==e?g+=d:h(b,a+1,d,"\\"):"/"==c[b][a]?"\\"==e||"A"==e?g+=d:h(b,a-1,d,"/"):"A"==c[b][a]?"A"==e||"\\"==e||"/"==e?g+=d:(h(b,a-1,d/2,"A"),h(b,a+1,d/2,"A")):h(b+1,a,d,c[b][a]))}for(var g=0,m=0,k=0;k<c.length;k++)for(var l=0;l<c[k].length;l++)"f"==c[k][l]&&(h(k+1,l,1),m++);alert(g/m)};

Javascript, 204 байта (Задача 2)

function f(c){function e(b,a,d){b<c.length&&0<=a&&a<c[0].length&&("\\"==c[b][a]?"/"!=d&&"A"!=d&&e(b,a+1,"\\"):"/"==c[b][a]?"\\"!=d&&"A"!=d&&e(b,a-1,"/"):"A"==c[b][a]?"A"!=d&&"\\"!=d&&"/"!=d&&(e(b,a-1,"A"),e(b,a+1,"A")):(" "==c[b][a]&&(c[b][a]="*"),e(b+1,a,c[b][a])))}for(var g=0;g<c.length;g++)for(var h=0;h<c[g].length;h++)"f"==c[g][h]&&e(g+1,h)};

Javascript, 238 байт (Задача 1 + 2)

function f(c){function h(b,a,d,e){b<c.length&&0<=a&&a<c[0].length&&("\\"==c[b][a]?"/"==e||"A"==e?g+=d:h(b,a+1,d,"\\"):"/"==c[b][a]?"\\"==e||"A"==e?g+=d:h(b,a-1,d,"/"):"A"==c[b][a]?"A"==e||"\\"==e||"/"==e?g+=d:(h(b,a-1,d/2,"A"),h(b,a+1,d/2,"A")):(" "==c[b][a]&&(c[b][a]="*"),h(b+1,a,d,c[b][a])))}for(var g=0,m=0,k=0;k<c.length;k++)for(var l=0;l<c[k].length;l++)"f"==c[k][l]&&(h(k+1,l,1),m++);alert(g/m)};

Как пользоваться

Обеспечьте двухмерное представление карты. Вот пример, приведенный в вопросе:

var input = [["f"," "," ","f"," "," ","f"," "," "],[" "," "," "," "," "," ","A"," "," "],[" "," "," ","A"," ","/"," ","\\"," "],["\\"," ","/"," "," "," "," "," ","A"],[" "," "," "," ","A"," ","\\","/"," "],[" "," "," ","/"," "," "," "," "," "],[" ","\\","/"," "," "," "," "," "," "]];
f(input);

Выход

Задача 1: Он просто создаст диалоговое окно (предупреждение) с результатом (0,75 для примера выше).

Задача 2: Он напрямую изменит карту. Должен ли я распечатать это? Если так, будет ли console.log принят? как действительный вывод?

Задача 1 + 2: оба из вышеперечисленных, очевидно, ...


Вода продолжает течь между персонажами, как будто она обнимает линии Aили косые черты. Я уточнил это в вопросе.
Увлечения Кэлвина

Вопрос гласитOutput must go to stdout.
user80551

Вы указали в качестве входного формата, что у вас есть массив из односимвольных строк на строку, но имейте в виду, что вы можете индексировать str[0]строки. Это был бы массив строк вместо массива символов.
Томсминг

1
user80551 Спасибо, я не знаю, почему это выскользнуло из головы. Я обновлю свой код как можно скорее. @tomsmeding Да, это работает для моего ответа на задание 1. Но для задания 2 Я напрямую изменяю ввод, и вы не можете изменить символ в строке, используя str [i], следовательно, использование массива массивов.
refreshfr

2

Python 3, 186 байт (задача 3)

Я взял идею сетки из ответа VisualMelon . Функция должна выводить действительную сетку в стандартный вывод для произвольно больших T и K, если это возможно (конечно-размерная сетка), конечно.

from fractions import*
def c(T,K):
 p=print;g=gcd(T,K);K//=g;T//=g
 if T&(T-1):p('Impossible')
 else:
  p(' f ')
  while T-1:
   T//=2;p('A/'[K<T]+'A \n///')
   if K>=T:K-=T
  p('AAA'*K)

Как пользоваться

Вызовите cфункцию с общей суммой и суммой, чтобы сохранить в качестве аргументов.

>>> c(24, 9)
 f 
/A 
///
AA 
///
AA 
///

>>> c(6, 2)
Impossible
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.