# Lumberjaxe Code Golf

Tom the lumberjack is going to do his daily routine: chop trees. After all, it's his job to do so. His boss has ordered him to chop trees in a straight line marked with a special tape to identify them, so he knows which trees he is going to have to chop. However, Tom quickly realizes he has a problem. His axe will only chop so much wood before breaking, and he forgot to bring a spare with him. Plus, the trees are different sizes. A small tree, marked with an i, will take 2 swings of the axe to chop, and a large tree, marked with an | will take 4 swings. Can Tom chop all of the assigned trees?

The Objective

Given two inputs, a string that determines the sequence of small and large trees and an integer that determines the durability of the axe, create a program that determines not only if Tom's axe will break or not, but also determine how many of each tree type he chopped down. It's , so the shortest code in bytes wins!

Example

Input 1 example:i||iii| This input string determines the sequence of trees.

Input 2 example:50 This input integer determines the durability of the axe.

The outputs for this particular example will be a boolean and a string as follows(True means Tom's axe broke): False 4 small, 3 big

• How flexible is the output format? Would [ false, [ 4, 3 ] ] work as well? Jul 5, 2020 at 23:16
• Can you give more examples with edge cases, e.g. 20 durability? Should the axe break on the last swing of i||iii| or not?
– xash
Jul 5, 2020 at 23:44
• You should wait at least 1 week before accepting an answer. And since this is a code-golf challenge, you should accept the shortest one. (PS: On CGCC, it's also perfectly fine to never accept any answer.) Jul 6, 2020 at 0:23
• Some more examples will make for a better challenge. Jul 6, 2020 at 20:24
• @NipDip: "Sure, as long as I can read the input its fair game." So, using 2 for i and 4 for | in the input is OK? Jul 6, 2020 at 20:56

# JavaScript (Node.js), 52 bytes

Takes input as (b)(n), where b is a Buffer (using the characters described in the challenge) and n is the durability of the axe.

Returns a Boolean value and 2 integers as [ broken, [ small, big ]].

b=>n=>[b.some(c=>(n-=6&c+1)<0||!++a[c%3],a=[0,0]),a]


Try it online!

### How?

Given an ASCII code c, we use 6 & (c + 1) to get the number of swings needed to chop the tree, and c % 3 to get an index into the tree-counting array a[] (0 for small, 1 for big).

 char. | c = ASCII code | 6 & (c + 1) | c % 3
-------+----------------+-------------+-------
'i'  |       105      |      2      |   0
'|'  |       124      |      4      |   1


# 05AB1E, 20 bytes

-5 bytes thanks to Kevin Cruijssen.

ηʒÇ3%·ÌO@}θD¹Ês{γ€g‚


Try it online!

## Explanation

η                    Prefixes of the input. ["i", "i|", "i||", "i||i", "i||ii", "i||iii", "i||iii|"]
ʒ                   Filter:
Ç                      Ord codes. E.g. "i||i" -> [105, 124, 124, 105]
3%                    Mod 3.          ->        [0, 1, 1, 0]
·                   Double.         ->        [0, 2, 2, 0]
Ì                  Add 2.          ->        [2, 4, 4, 2]
O                 Sum the prefix. ->        12
@}               Does it exceed
the second input? -> 50 >= 12 -> 1

θ              The last item of the filtered prefixes: "i||iii|"
D             Duplicate.
¹Ê           Is it not equal to the first inupt?     "i||iii|" != "i||iii|" -> 0
s          Swap the other copy up.                 "i||iii|"
{         Sort.                                   "iiii|||"
γ        Group by consecutive equal items.       ["iiii","|||"]
€g      Map: length.                            [3, 4]
‚     Pair.                                   [0, [3, 4]]

• Nice approach. Some things to golf: the leading S can be removed; the Os‹ can be O›; and the Dg¹g‹sJθ can be θD¹Ês: try it online - 20 bytes. Jul 6, 2020 at 7:48
• I think you have an off by one error (or need to use >= in place of >) - e.g. this should return [0, [1, 1]]. Also is it acceptable to return [[],[]] when we can't cut the first tree, or [[0],[x]] when we make it through the first x trees which happen to be of the same type? Jul 6, 2020 at 17:08

# R, 63 bytes

using characters exactly as described in challenge (or only 54 bytes using 0,1 to represent small & big trees, and outputting 0,1 to represent FALSE/TRUE axe breaking).

function(a,t)list(sum(c<-2+2*(t<"i"))>a,table(t[cumsum(c)<=a]))


Try it online!

# J, 3734 33 bytes

(](-:;+/@#:@])(>:2*+/\)#])' i'i.]


Try it online!

-1 byte thanks to Bubbler

Converts small to 1, big to 2. Now create a filter by doubling and scan summing, and apply filter to find entries less than or equal to the left input. Take just those entries, convert to binary, and sum to get the <num big>, <num small> part of the answer. Check if the filtered list equals the unfiltered list to get the "chops down all trees?" part of the answer.

• You can omit the last char | in ' i|'i.]. Jul 6, 2020 at 6:43

# Python 2, 103 $$\\cdots\$$ 82 80 bytes

Saved 4 6 9 11 bytes thanks to ovs!!!

f=lambda s,n:n<sum(6&ord(t)%6for t in s)and f('<'+s[:-1],n)or map(s.count,"<i|")


Try it online!

Inputs a string of trees $$\s\$$ (as is and |s) and an axe durability $$\n\$$.
Outputs a list of [axe broken, small trees, large trees] where axe broken is truthy if Tom's axe broke (or falsy otherwise) followed by the number of trees cut down.

How

If $$\c\$$ is either i, | or < then: $$\text{6&ord(c)%6} = \left\{ \begin{array}{ll} 2 \text{ if c is 'i'}\\ 4 \text{ if c is '|'}\\ 0 \text{ if c is '<'} \end{array} \right.$$

this is summed for all the trees in $$\s\$$ to calculate its needed durability. If it's too much for Tom's axe then we repeatedly try again without the last tree and set Tom's axe as broken by inserting a < into $$\s\$$, making that count truthy. When Tom's axe us strong enough we return what happened to his axe along with the number of each tree still in $$\s\$$.

• (h,[*map(s.count,"i|")]) for -4.
– ovs
Jul 6, 2020 at 19:39
• @ovs Nice one - thanks! :-) Jul 6, 2020 at 20:14
• If you modify the output format slightly, it is 85 bytes
– ovs
Jul 6, 2020 at 20:45
• @ove Nice two - thanks again! :D Jul 6, 2020 at 20:53
• A last one: if you output a truthy/falsy value instead of 1/0, 82 bytes (or 80 bytes in Python 2) are possible.
– ovs
Jul 6, 2020 at 21:13

# Keg, 32 bytes

0:&®s?⑷¦i2⑹|\|4©s⑨®s±™⑸¿⅀0=⑻©s(.


Try it online!

Takes input as trees, durability and outputs big, small and whether or not the axe breaks.

Somehow, Keg beat pyth.

# Jelly, 14 bytes

I'm assuming, for now, that the "boolean" part of the output may be given as a Truthy/Falsey value.

Og©2ḤÄ’<a®‘ċⱮ3


A dyadic Link accepting the trees (a list of characters) on the left and the axe durability (an integer) on the right which yields a list of three integers, [is_broken, small_trees, big_trees] (Note that non-zero integers are Truthy in Jelly while 0 is Falsey).

Try it online!

### How?

Og©2ḤÄ’<a®‘ċⱮ3 - Link: list of characters, T; integer, D   e.g. "|i|iii"; 14
O              - Ordinals (T)                                   [124,105,124,105,105,105]
©            - copy this to the register and yield it:
g 2           -   greatest common divisor with two             [2,1,2,1,1,1]
Ḥ          - double                                         [4,2,4,2,2,2]
Ä         - cumulative sums                                [4,6,10,12,14,16]
’        - decrement                                      [3,5,9,11,13,15]
<       - less than (D)?                                 [1,1,1,1,1,0]
a      - logical AND with:
®     -   recall the value from the register           [2,1,2,1,1,0]
‘    - increment                                      [3,2,3,2,2,1]
Ɱ3 - map across 3 with: (i.e. for right in [1,2,3])
ċ   -   count occurrences                            [1,3,2]


# Python 3.8, 109 bytes

f=lambda l,n,a=0,b=0:f(l[1:],m,a+1-j,b+j)if l and(m:=n-((j:='i|'.index(l[0]))+1)*2)>=0 else[l!=''and m<0,a,b]


Try it online!

• @Alexley I have a found a 107 byte solution by placing f= in the header.Try it online! Jul 11, 2020 at 12:39
• @Tanmay thanks for the sugession, but the function is recursive, so f is a part of the code. Alternatively, why don't we move all the function into the header instead?) $0$ bytes. Jul 11, 2020 at 15:04

# Retina 0.8.2, 55 bytes

\d+
$* (11)+1?(?<-1>(i)|(?<-1>(\|)))*($)?.*
$#4$#3 $#2  Try it online! Takes input as [durability][trees] without a separator and outputs [complete] [big] [small]. Explanation: \d+$*


Convert the durability to unary.

(11)+1?


Capture half the durability as $#1. (?<-1>(i)|(?<-1>(\|)))*  Count the trees as they are matched, and decrement the remaining durability appropriately depending on the size of tree. ($)?.*


Determine whether the all of the trees were chopped down.

$#4$#3 \$#2


Output the desired results.

# Desmos, 73+31+8+8 = 125 120 bytes

-5 bytes from finding a new builtin, which cost a few bytes but allowed three functions to be collapsed into one.

l(g)=\sum_{m=1}^{t.length}\left\{2*\sum_{n=1}^m t[n]<=d:g[t[m]],0\right\}
\left\{d-total(t)*2<0:1\right\}
l([1,0])
l([0,1])


(each line is an individual function, line breaks are not used and don't count towards bytes)

Try it online

Desmos is absolutely the wrong choice of language for this problem.

Input is taken as a variable t holding the trees as an array of 1s and 2s, representing 2s and 4s (as accepted in the comments, Desmos doesn't even support strings anyways) / small and large trees and a variable d holding the durability. Output is in the second function (will it break, undefined for no and 1 for yes) and third and fourth functions (short and tall trees chopped respectively.

Explanation:

l(g)=\sum_{m=1}^{t.length}\left\{2*\sum_{n=1}^m t[n]<=d:g[t[m]],0\right\}


Calculates the amount of trees of a certain type chopped. It goes through each tree, checks if it has enough durability to chop it with the inner sum, and if so, adds a 1 or a 0 depending on the tree type, based on a lookup array g passed to it.

\left\{d-total(t)*2<0:1\right\}


Simple calculation to check if the durability available is less than what's required. Fun fact: Desmos can't properly output truthy or falsey values! It does support true and false, as you can see if you plug in \left\{3>2:1,0\right\} (where 3>2 evaluates to true, causing 1 to be output instead of 0), but you can't actually get then to print. Plug in 3>2 and you don't get any output. Additionally, try to use values we might traditionally think of as truthy or falsey in those same formulas, and you get an error! For this reason, it's possible that this isn't technically a truthy/falsey output based on this, but that definition allows for the occasional exception, which I think this fits under. I think we can all agree that 1 is truthy and undefined is falsey, so that's what I've gone with here. A looser definition (for example, any positive number is truthy and 0, undefined, and negatives are falsey) would likely allow for this line to be shorter.

l([1,0])


Calculate 1 (short) trees chopped with a 1 in position 1.

l([0,1])


Calculate 2 (tall) trees chopped with a 1 in position 2.

• "desmos is absolutely the wrong choice of language for this problem." I admire the stubbornness. Aug 23, 2020 at 17:08