Код (міні) гольф


50

Враховуючи збоку майданчика для міні-гольфу та силу гойдалки, визначте, чи м'яч увійде в яму.


Курс буде в такому форматі:

      ____       ____ _   
   __/    \     /    U \  
__/        \   /        \_
            \_/           

Куля починається безпосередньо перед першим шматочком землі зліва і слідкує за контуром ходу, поки не досягне отвору (верхній регістр Uнижче поточного рівня землі). Якщо він досягне отвору, виведіть триєдне значення. Потужність гойдалки буде початковою швидкістю м'яча. М'яч переходить до наступного символу праворуч при кожній ітерації, тоді швидкість змінюється залежно від символу, на якому він зараз ввімкнений. Якщо швидкість досягає 0меншої швидкості перед отвором, виведіть значення фальси.

  • _ зменшує швидкість на 1
  • / зменшує швидкість на 5
  • \ збільшує швидкість на 4

Курси за бажанням можна залити пробілами. Сила гойдалки завжди буде додатним цілим числом.

Вам не потрібно турбуватися про те, що м'яч буде надто швидким, щоб увійти в яму, котившись назад або стрибаючи / підстрибуючи з пагорбів.

Випробування

Input: 27
      ____       ____ _   
   __/    \     /    U \  
__/        \   /        \_
            \_/           
Output: true

----------

Input: 26
      ____       ____ _   
   __/    \     /    U \  
__/        \   /        \_
            \_/           
Output: false

----------

Input: 1

U
Output: true

----------

Input: 1
_ 
 U
Output: false

----------

Input: 22

     /U
    /  
   /   
  /    
\/     
Output: true

----------

Input: 999
_       _
 \     / 
  \   /  
   \ /   
    U    
Output: true

----------

Input: 5
  /
/U 
Output: false

----------

Input: 9

/\/\/\/\/U
Output: false

----------

Input: 16

_/\                                         _
   \      __       /\/\/\                  / 
    \    /  \     /      \                /  
     \__/    \   /        \____________ _/   
              \_/                      U     

Output: true

Це кодовий міні-гольф, найкоротша відповідь у байтах виграє!


1
Якщо у вашій мові є хороші вбудовані масиви, ви можете перетворити вхід у потік операцій ( \_/), виконавши наступні кроки: розділити на масив рядків, обертати, вирівняти, пропустити пробіли.
Кіос

1
Це дійсно більше механізм фіксованої колії, ніж поле для гольфу: П
Зах Гейтс

24
Мені подобається, що \/\/\/\/\/це більш ефективний курс, ніж __________.
ezrast

2
Це я думав, 4 вниз, 5 вгору, то .5 повинно бути середнім. О, квартира - 1?
Лейф Віллерц

Чи завжди кожен рядок у курсі буде однакової довжини (із пробілами, заповненими в кінці коротших рядків)?
ХропінняFrog

Відповіді:


17

Піт, 27 байт

.Am<sXsd"_\ /"[1_4Z5)Q._C.z

Демонстрація

Цей код робить щось дуже розумне і зовсім не безпечне X. Перевірте це нижче.

Пояснення:

.Am<sXsd"_\ /"[1_4Z5)Q._C.z
                               Implicit: Z = 0, Q = eval(input())
                               Q is the initial power.
                         .z    Take all input, as a list of lines.
                        C      Transpose, giving all columns.
                      ._       Form all prefixes.
  m                            Map over the prefixes.
      sd                       Concatenate the prefix.
     X  "_\ /"[1_4Z5)          Change '_' to 1, '\' to -4, ' ' to 0, and '/' to 5.
                               In particular, 'U' is left unchanged.
    s                          Reduce on addition.
                               If all elements were numbers,
                               this results in the total change in power.
                               If there was a 'U', it results in a string.
   <                 Q         If the previous result was a number, this compares
                               it with the initial input to see if the ball is
                               still rolling.
                               If the previous result was a string, this slices off
                               the first Q characters, which always has a truthy
                               result.
.A                             Test whether all of the prefixes mapped to a thruthy
                               result.

Я можу чогось бракувати, але чи зупиняється на цьому Q? Тобто останній приклад може викликати деякі проблеми?
фліндеберг

@flindeberg Це не так, як це працює. У < ... Qпрацює як порівняння чисел аж до отвору, а НЕ шматочок. Після дірки важливо лише те, що результат - простий.
isaacg

14

Haskell, 111 109 байт

import Data.List
g"_"=1
g"/"=5
g _= -4 
f n=all(>0).scanl(-)n.map g.fst.span(/="U").(>>=words).transpose.lines

Приклад використання:

*Main> f 27 "      ____       ____ _   \n   __/    \\     /    U \\  \n__/        \\   /        \\_\n            \\_/           "
True
*Main> f 26 "      ____       ____ _   \n   __/    \\     /    U \\  \n__/        \\   /        \\_\n            \\_/           "
False

Як це працює:

                            lines  -- split into list of lines at nl
                       transpose   -- transpose
                  (>>=words)       -- turn each line into words (i.e. remove spaces)  
            fst.span(/="U")        -- take all words up to but excluding "U"
         map g                     -- turn each word into the speed modifier
    scanl(-)n                      -- build list of partial sums starting with n
                                   --   note: speed modifiers are negative so we
                                   --   use (-) with scanl to build sums 
all(>0)                            -- return true if all sums are greater than 0                                 

Редагувати: @ user81655 знайдено 2 байти для збереження. Дякую!


7

Рубі, 104 87 символів

->s,t{t.lines.map(&:bytes).transpose.map{|o|(c=o.max)==85||s<0?break: s+=c*3%14-6}
s>0}

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

2.1.5 :001 > track = '      ____       ____ _   
2.1.5 :002'>    __/    \     /    U \  
2.1.5 :003'> __/        \   /        \_
2.1.5 :004'>             \_/           
2.1.5 :005'> '
 => "      ____       ____ _   \n   __/    \\     /    U \\  \n__/        \\   /        \\_\n            \\_/           \n" 

2.1.5 :006 > ->s,t{t.lines.map(&:bytes).transpose.map{|o|(c=o.max)==85||s<0?break: s+=c*3%14-6};s>0}[27, track]
 => true 

2.1.5 :007 > ->s,t{t.lines.map(&:bytes).transpose.map{|o|(c=o.max)==85||s<0?break: s+=c*3%14-6};s>0}[26, track]
 => false 

6

Japt, 38 байт

Vz r"%s|U[^]*" ¬e@UµX¥'_?1:X¥'/?5:-4 ¬

Try it here!

Побої CJam!

Пояснення

В основному приймає рядок введення, обертає його на 90 градусів за годинниковою стрілкою, викреслює пробіли та нові рядки, видаляє отвір і все, що знаходиться після нього, і розбивається по символах. Потім перевіряє, чи куля коли-небудь потрапляє до нуля або нижче за допомогою everyфункції.


Я думаю, що `` повинно бути позитивним (опис виглядає неправильним)
isaacg

Я не думаю, що це працює. Зобразіть це: серія схилів набирає швидкість кулі до -2, але згодом є сітка +4. Сума відображала б +2, тому м'яч зробив це. Насправді вона ніколи не дістанеться до позитивного розділу після досягнення негативів.
Кіос

Я думаю, що вирішив проблему.
Mama Fun Roll

Це класна кнопка;)
J Atkin

Приємно! Отже, гольф ... Подвійний нахил може бути замінений на %, і >0його можна замінити ¬, оскільки sqrt непозитивного числа завжди є хибним ( 0 -> 0, -1 -> NaN).
ETHproductions

6

CJam, 40 39 байт

liqN/:.e>'U/0="\_/"[4W-5]er{1$+}/]:e<0>

Вхід має потужність на першому рядку, а курс починається на другому. Вихід 0або 1.

Перевірте це тут.

Пояснення

li    e# Read power and convert to integer.
qN/   e# Read course and split into lines.
:.e>  e# Flatten course by folding maximum over columns.
'U/   e# Split around the hole.
0=    e# Keep the first chunk.
"\_/"[4W-5]er
      e# Replace \, _, / with 4, -1, 5, respectively.
{     e# For each of those costs...
  1$+ e#   Copy the previous power and add the cost.
}/    e# This leaves all partial sums on the stack.
]     e# Wrap them in an array.
:e<   e# Find the minimum.
0>    e# Check whether it's positive.

5

Сітківка, 82 81 77 74 68 67 68 байт

+`(?<=(.)*) (?=.*¶(?<-1>.)*(.))
$2
\\
>>>>
+`>_|>{5}/|>¶

^>*U

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

  • Введення представлено в одинарній базі , як n >s - наприклад, 4 є >>>>\n. (це законно?)
  • +`(?<=(.)*) (?=.*¶(?<-1>.)*(.)) $2 - вирівняти хід - замінити пробіли символом під ними.

    Після цього етапу дані будуть виглядати приблизно так:

    >>>>>>>>>>>>>>>>>>>>>>>>>>
    __/__/____\\\_///____U_\\_
    __/__/    \\\_///    U \\_
    __/        \\_//        \_
                \_/           
    

    Ми можемо просто ігнорувати все після першого U, ми все одно не дійдемо туди.

  • > являють собою крок, який нам дозволено зробити, або енергію, що залишилася.
  • Замініть кожного \на чотири >- нахил дає нам додаткову енергію.
  • Петля: пильно зніміть >_або >>>>>/поки не залишиться жодної. _s і /s споживають енергію.
  • Нарешті, спробуйте співставити ^>*U- перевірте, чи можемо ми досягти Uпозитивної енергії (чи немає енергії).
    Цей вихід буде 0або 1.

Ще один близький варіант з 91 79 байтами:

+`(?<=¶(.)*) (?=.*¶(?<-1>.)*(.))
$2
^(>)+\n(?<-1>_|/(?<-1>){4}|\\(?<1>){5})+U

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

Це той самий підхід, але з балансуючою групою замість спірної заміни.

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


1
Так, одинарне введення є легітимним (якщо виклик не вказує "десятковий"), хоча я, мабуть, використовую 0або 1як цифру, якщо це не містить додаткових байтів.
Мартін Ендер

1
Також ласкаво просимо до PPCG, я дуже рада бачити вас тут! :) (І використовуючи також Retina.)
Мартін Ендер

Звичайно! Це було у гарячому списку питань і виглядало весело. Я подумав, що спробую :-)
Кобі

3

ES6, 117 байт

(c,p)=>c.split`
`.map(s=>[...s.slice(0,c.match(/^.*U/m)[0].length-1)].map(c=>p+=c=='/'?-5:'    \\'.indexOf(c)))&&p>0

Безголівки:

function hole(course, power) {
    width = course.match(/^.*U/m)[0].length - 1; // calculate width to hole
    lines = course.split("\n");
    for (i = 0; i < lines.length; i++) {
        line = lines[i].slice(0, width); // ignore extraneous parts of the course
        for (j = 0; j < line.length; j++) {
            switch (line[j]) { // accumulate remaining power
            case '/': power -= 5; break;
            case '\\': power += 4; break;
            case ' ': break;
            default: power--; break;
            }
        }
    }
    return power > 0;
}

Редагувати: збережено 4 байти завдяки ՊՓԼՃՐՊՃՈԲՍԼ.


@ ՊՓԼՃՐՊՃՈԲՍԼ Дякую, я намагаюся оптимізувати швидкість ...
Ніл

3

JavaScript (ES6), 108 107 106 байт

Це рішення, яке я придумав, коли створив виклик.

(p,c)=>[...(l=c.split`
`)[w=0]].map((_,i)=>l.map(t=>(g=t[i])-1|p<=0?0:p-=g>"]"?1:g>"U"?-4:g>"/"?w=1:5))&&w

Пояснення

Приймає силу як число, а курс - як рядок. Повернення 1для trueабо 0для false. Курс повинен бути прокладений пробілами.

(p,c)=>
  [...(l=c.split`
`)                          // l = array of lines
  [w=0]]                    // w = true if the ball has entered the hole
.map((_,i)=>                // for each index i
  l.map(t=>                 // for each line t
    (g=t[i])                // g = the character at the current index
    -1|p<=0?0:              // do nothing if g is a space or the ball has no speed left
    p-=
      g>"]"?1               // case _: subtract 1 from p
      :g>"U"?-4             // case \: add 4 to p
      :g>"/"?w=1            // case U: set w to true (it doesn't matter what happens to p)
      :5                    // case /: subtract 5 from p
  )
)
&&w                         // return w

Тест

var solution = (p,c)=>[...(l=c.split`
`)[w=0]].map((_,i)=>l.map(t=>(g=t[i])-1|p<=0?0:p-=g>"]"?1:g>"U"?-4:g>"/"?w=1:5))&&w
Power = <input type="number" id="power" value="16" /><br />
<textarea id="course" rows="6" cols="50">_/\                                         _
   \      __       /\/\/\                  / 
    \    /  \     /      \                /  
     \__/    \   /        \____________ _/   
              \_/                      U     </textarea><br />
<button onclick="result.textContent=solution(+power.value,course.value)">Go</button>
<pre id="result"></pre>


3

Python (3,5) 169 160 байт

Рекурсивне рішення без функції транспонування (zip)

def f(c,p):c=c.splitlines();l=len(c);f=lambda x,h,v:v if'U'==c[h][x]or v<1 else f(x+(h==l-1),(h+1)%l,v+{"_":-1,"\\":4,"/":-5," ":0}[c[h][x]]);return f(0,0,p)>0

Безумовно

c, звичайно, p для потужності, v для швидкості, h для висоти

def f(c,p):
    c=c.splitlines()
    l=len(c)
    tmp = {"_":-1,"\\":4,"/":-5," ":0}
    f=lambda x,h,v:v if'U'==c[h][x]or v<1 else f(x+(h==l-1),(h+1)%l,v+tmp[c[h][x]])
    return f(0,0,p)>0

Використання

f(16,"_/\                                         _\n   \      __       /\/\/\                  / \n    \    /  \     /      \                /  \n     \__/    \   /        \____________ _/   \n              \_/                      U     ")
f(9,"/\/\/\/\/U")

2

Pyth, 35 байт

VC.z=-Q@(1_4 5)x"_\\/"JrN6IqJ\U>Q_5

Пояснення

                                    - Autoassign Q = eval(input())
                                    - Autoassign .z = rest of input
VC.z                                - For N in zip(*.z)
    =-Q                             - Q -= ...
                      JrN6          - Autoassign J to N.strip() (get rid of spaces)
       @(1_4 5)x"_\\/"              - {"_":1, "\\": -4, "/": 5, "U":5}[J] ("U" isn't defined but that's what it is according to how str.index works)
                          IqJ\U     - If J == "U"
                               >Q_5 - print Q > -5 ()

1

Рубі, 85 символів

->i,s{s.lines.map(&:bytes).transpose.any?{|o|(c=o.max)==85||i<0||!(i+=c*3%14-6)};i>0}

Відповідь @ manatwork відповідь


1

JavaScript, 266 263 244 байт

(s,a)=>{var f=(e,x)=>{for(var i=1;D=e[i][x],i<e.length;i++)if(D!=" ")return D},o=a.split(`
`),l=o.reduce((a,b)=>Math.max(a.length||a,b.length)),b="";for(i=0;i<l;i)b+=f(o,i++);for(i=0;b[i]!="U"&&s>0;i++)s-=b[i]=="_"?1:b[i]=="/"?5:-4;return s>0}

Безумовно

(s,a)=>{
    var f=(e,x)=>{
        for(var i=1;D=e[i][x],i<e.length;i++)
            if(D!=" ")
                return D
    },
    o=a.split(`
`),
    l=o.reduce((a,b)=>Math.max(a.length||a,b.length)),
    b="";
    for(i=0;i<l;)
        b+=f(o,i++);
    for(i=0;b[i]!="U"&&s>0;i++)
        s-=b[i]=="_"?1:b[i]=="/"?5:-4;
    return s>0
}

Використання

var o = (s,a)=>{var f=(e,x)=>{for(var i=1;D=e[i][x],i<e.length;i++)if(D!=" ")return D},o=a.split(`
`),l=o.reduce((a,b)=>Math.max(a.length||a,b.length)),b="";for(i=0;i<l;)b+=f(o,i++);for(i=0;b[i]!="U"&&s>0;i++)s-=b[i]=="_"?1:b[i]=="/"?5:-4;return s>0}


o(27, `
      ____       ____ _   
   __/    \\     /    U \\  
__/        \\   /        \\_
            \\_/           `); // will return true

Моя помилка; Я думав, що скопіював у першому прикладі "27" як перший аргумент. Я це виправив. Дякую.
користувач49328

1

Java, 219 байт

boolean p(int v,String c){int z=c.length(),f[]=new int[z],e,i,k;for(String r:c.split("\n"))for(i=-1;++i<r.length();)if((e=r.charAt(i))>32)f[i]=e;for(i=-1,e=0;++i<z&v>0;)v-=(k=f[i])>94?1:k>91?-4:k>84?(e=1):5;return 0<e;}
  • Згладьте хід, оскільки координата y не має значення, на жаль, у Java немає вертикальної обрізки. У нього також немає рядка-транспонирования.

  • Ітерайте по сплющеному ходу і стежте за швидкістю м'яча.


1

Октава, 111 110 байт

function g(v,s) A([95,47,92])=[1,5,-4];all(v>cumsum(A(m=max(cat(1,strsplit(s,'\n'){:}),[],1)))(1:find(m==85)))

Пояснення:

  • Розділіть введення на нові рядки та перетворіть цей дратівливий масив комірок у матрицю
  • Вирівняйте матрицю, знайшовши maxдля кожного стовпця
  • Карта символів '_/\'в [1, 5, -4](всі інші символи менше , ніж '_'зіставляються 0)
  • Обчисліть сукупну суму всіх елементів відображеного масиву
  • Вихід, Trueякщо всі сукупні суми від початку курсу до чашки менші за швидкість старту ( Falseінакше).

Ось тестовий випадок, який я вже розробив аналогічно другому, запропонованому @Erwan, і пара результатів:

s9 =
   /\
  /  \
_/    \
       \
        \
         U

g(11,s9) %False
ans = 0
g(17,s9) %True
ans =  1

І ось перший тестовий випадок:

s10 = 
  _
 / U\
/    \
      \
       \
        \
         \
          \_

>> g(11,s10)
ans = 0
>> g(12,s10)
ans =  1

я думаю, якщо курс схожий "//_U\\\\\\\_на результат неправильний, оскільки ви не знімаєте персонажів за Uтими самими речами, якщо у вас є курс з локальним максимумом, наприклад_//\\\\\U
Ерван

@Erwan Але я б видалити символи після U. Ось що (1:find(m==85))робить; він займає підмасив від першого індексу до місця розташування U. Я перевірю ваш тестовий випадок з парою стартових швидкостей і повернуся до вас.
стакан

Я не міг запустити ваше рішення (у мене немає Octave), тому я просто запитую ... і тому, що я знаходжу проблему з локальними максимумами в іншому рішенні python :) нарешті ваше рішення працює з локальними максимумами, оскільки ви використовуєте сперму і не просто суму (не бачимо цього при першому читанні)
Ерван

@Erwan Я додав два запропоновані вами тестові справи. Будь ласка, подивіться і перевірте, чи є результати, які ви очікуєте. Якщо ви намагаєтеся це зробити в MATLAB, ви не зможете запустити його, оскільки він використовує деяку індексацію, яка працює лише в Octave. Вам доведеться призначити результат cumsumпроміжної змінної, а потім використовувати її для остаточного порівняння all(v>tmp(1:find(m==85))).
стакан

Ваша робота з рішенням прекрасно пропускає багато речей під час першого читання (просто тестуйте в Matlab так багато проміжних змінних, щоб додати)
Ерван

0

C, 629 байт

#include <string.h>
#include <stdlib.h>
#include <string.h>

bool swing(char *c, unsigned int p)
{
    char *olc = calloc(strlen(c), 1);
    int x = 0;
    char *n = c;

    while(1) {
        if(*n == '\0')  break;
        else if(*n == ' ') x += 1;
        else if(*n == '\n') x = 0;
        else {
            olc[x] = *n;
            x += 1;
        }
        n++;
    }

    int hd = 0;
    for(char *i = olc; i != strchr(olc, 'U'); i++) {
        if(*i == '_') hd += 1;
        else if(*i == '/') hd += 5;
        else hd -= 4;
    }

    free(olc);
    if(hd < p) return 1;
    return 0;
}

Безголівки:

bool swing(char *course, unsigned int power)
{
    const size_t course_len = strlen(course);
    char *one_line_course = calloc(course_len, sizeof(char));
    assert(one_line_course);
    int x_pos = 0;
    char *next = course;

    //Convert to one line representation
    while(1) {
        if(*next == '\0') {
            break;
        }
        else if(*next == ' ') {
            x_pos += 1;
        }
        else if((*next == '\n') || (*next == '\r')) {
            x_pos = 0;
        }
        else {
            one_line_course[x_pos] = *next;
            x_pos += 1;
        }
        next++;
    }

    //Calculate power vs distance
    const char *hole_location = strchr(one_line_course, 'U');
    int hole_distance = 0;
    for(char *i = one_line_course; i != hole_location; i++) {
        if(*i == '_') {
            hole_distance += 1;
        }
        else if(*i == '/') {
            hole_distance += 5;
        }
        else {
            hole_distance -= 4;
        }
    }

    free(one_line_course);
    if(hole_distance < power) {
        return true;
    }
    else {
        return false;
    }
}

В основному я просто роблю один прохід, щоб перетворити вхідний рядок, щоб вмістити все в одному рядку


Ласкаво просимо до головоломки програмування та коду для гольфу! Ви можете (і повинні) мати можливість значно зменшити розмір, усунувши більшість пробілів; ви можете зменшити деякі ваші if/ elseнапр x+=*n==' ')?1:*n=='\n'?-x:(olc[x]=*n,1. Ще одна порада: в C unsigned intможна записати unsigned, заощадивши відразу 4 байти.
Toby Speight

0

Пітон, 212 201 188 143 байт

Велика заслуга цієї ітерації цього сценарію припадає на @Erwan, який дав мені зовсім інший підхід до спробу та кілька порад, які врятували мені в кінці 55 байт.

Не є рекурсивним, тому має суттєво відрізнятися від інших пітонних розчинів.

def g(c,p):
 o=[''.join(x).split()[0] for x in zip(*c.split('\n'))]
 t={"_":1,"/":5,"\\":-4}
 for v in o:
    if v=="U" or p<1:return p>0
    p-=t[v]

Трохи невольфів:

def g(course,power):
  course=course.split('\n') # split into lines
  course=zip(*course) 

  #transpose and flatten course, then remove spaces
  one_line_course=[''.join(x).split[0] for x in zip(*course)] 

  terrain_values={"_":1,"/":5,"\\":-4}
  for char in one_line_course:
    if char=="U" or power<1: 
      return power>0 # true when power remains, false otherwise
    power-=terrain_values[char]

якщо ви хочете більш коротке рішення, ви можете скористатися наконечником Cyoce і використовувати вбудовану функцію транспонування. Щось таке, o=[''.join(x).split()[0] for x in zip(*c.split('\n'))]що виграє 40 байт, я думаю
Ерван

Ви можете також замінити breakна return p>0і видалитиif p...
Ервана

вам потрібно додати умову, if"U"==v or p<1 якщо є локальний максимум, наприклад_//\\\\\U
Ерван

@Erwan Ваша перша порада не працює, якщо лінії не однакової довжини (короткі лінії, що мають пробіли, щоб відповідати довгим). Оскільки в публікації сказано, що "Курси за бажанням можна залити пробілами", я не впевнений, що можна припустити, що це правда. Я про це запитав у коментарі.
ХропінняFrog

так, я припускаю, що всі лінії мають однакову довжину (вирівнюється пробілом), можливо, я помиляюся в цьому випадку, я думаю, що моє рішення погано
Ерван
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.