9
\$\begingroup\$

Given an input string, write a program that outputs the total number of lines and curves it has.

The Challenge

  • Take input from STDIN, or any other input method.
  • Output to STDOUT, or any other output method, the total number of lines and curves contained in the string, in that order, based on the below table in the code snippet.
  • Any non-alphanumeric characters should be ignored.
  • Standard loopholes are forbidden.
  • This is , so shortest code wins.

Clarifications

  • The lines and curves are determined by the font used on Stackexchange for code blocks.
  • Circles (like O, o, 0) and dots (i, j), are considered to be 1 curve each.
  • Input can be a string, list of characters, stream of characters, bytecodes etc.
  • Output can be an array of integers, tuple of integers, comma-separated string, etc. The two numbers must be separate, so 104 is not valid, but 10,4, 10 4, 10\n4, [10,4], (10, 4), and so on is.
  • Heading and trailing whitespace is perfectly acceptable.

Sample Input and Output

# Format: str -> line, curve
hi -> 4, 2
HELLO WORLD -> 20, 4
l33+ 5pEak -> 13, 8
+=-_!...?~`g@#$%^ -> 1, 2
9001 -> 5, 3
O o O o O o -> 0, 6

Character Table

Char | Lines | Curves
0    | 1     | 1
1    | 3     | 0
2    | 1     | 1
3    | 0     | 2
4    | 3     | 0
5    | 2     | 1
6    | 0     | 1
7    | 2     | 0
8    | 0     | 2
9    | 0     | 1
A    | 3     | 0
B    | 1     | 2
C    | 0     | 1
D    | 1     | 1
E    | 4     | 0
F    | 3     | 0
G    | 2     | 1
H    | 3     | 0
I    | 3     | 0
J    | 1     | 1
K    | 3     | 0
L    | 2     | 0
M    | 4     | 0
N    | 3     | 0
O    | 0     | 1
P    | 1     | 1
Q    | 0     | 2
R    | 2     | 1
S    | 0     | 1
T    | 2     | 0
U    | 0     | 1
V    | 2     | 0
W    | 4     | 0
X    | 4     | 0
Y    | 3     | 0
Z    | 3     | 0
a    | 0     | 2
b    | 1     | 1
c    | 0     | 1
d    | 1     | 1
e    | 1     | 1
f    | 1     | 1
g    | 1     | 2
h    | 1     | 1
i    | 3     | 1
j    | 1     | 2
k    | 3     | 0
l    | 3     | 0
m    | 3     | 2
n    | 2     | 1
o    | 0     | 1
p    | 1     | 1
q    | 1     | 1
r    | 1     | 1
s    | 0     | 1
t    | 1     | 1
u    | 1     | 1
v    | 2     | 0
w    | 4     | 0
x    | 4     | 0
y    | 1     | 1
z    | 3     | 0
\$\endgroup\$
  • 2
    \$\begingroup\$ What counts as a line and curve? Is s 2 curves or 1? Is the stem in j both a line and curve? It would be best if you could just list the required values for all of the letters. \$\endgroup\$ – Sriotchilism O'Zaic Jul 16 at 15:03
  • 4
    \$\begingroup\$ I really don't understand the downvotes on this one. For me this is a well specified challenge with good test cases, a reference implementation and a table of what values are expected (whether they are technicaly right or worng is a matter of personal opinion but nothing to do with the challenge)..Input and output are flexible. If someone can explain what is wrong with this I would be most grateful. \$\endgroup\$ – ElPedro Jul 16 at 17:44
  • 3
    \$\begingroup\$ Can you please provide the values for each character in a format that we can more easily copy; the Snippet is entirely unnecessary. \$\endgroup\$ – Shaggy Jul 16 at 18:22
  • 4
    \$\begingroup\$ o should be 0 lines, 1 curve \$\endgroup\$ – Giuseppe Jul 16 at 18:54
  • 2
    \$\begingroup\$ Continued from above...Downvotes with no feedback give OP little chance to improve their challenges in the future. \$\endgroup\$ – ElPedro Jul 17 at 20:21

17 Answers 17

8
\$\begingroup\$

Haskell, 214 199 188 175 bytes

 g 0=[]
 g n=mod n 5:g(div n 5)
 d#s=sum[n|c<-d,(i,n)<-zip['0'..]$g s,c==i]
 f s=(s#0x300BBD37F30B5C234DE4A308D077AC8EF7FB328355A6,s#0x2D5E73A8E3D345386593A829D63104FED5552D080CA)

Try it online!

The numbers of lines and curves are the digits of base-5 numbers and stored as base-16 numbers. Function g translates back to base-5.

Edit: -13 bytes thanks to @cole.

\$\endgroup\$
  • 1
    \$\begingroup\$ 169 bytes if you can take a list of charcodes. Going to explore porting this to the string variant… \$\endgroup\$ – cole Jul 17 at 3:58
  • 1
    \$\begingroup\$ 175 bytes if you have to use strings (deleted my previous comment since i golfed a trivial 3 bytes off). \$\endgroup\$ – cole Jul 17 at 5:48
  • \$\begingroup\$ @cole: thanks for the improvements. Going with a list of integers feels like cheating, because the challenge is tagged as "string". On the other hand, the rules allow "bytecodes" as a valid input format. However, many other answers also use some sort of char -> integer conversion. Don't know what to do. \$\endgroup\$ – nimi Jul 17 at 21:59
6
\$\begingroup\$

05AB1E, 78 69 65 bytes

-4 bytes thanks to Kevin Cruijssen, Go and check out his even better 05AB1E answer

žKÃÇ48-©•7ć_qýÊΣŸßαŽ_ì¡vFÛ–ÄÔ™”súyån!₁ζB?òrβÂ@µk₆¼×¬°•5в2ä`®èrè‚O

Try it online!

Outputs as [Curve, Line]

I'm really bad at 05AB1E I just found out. Can definitely save more bytes if I can get 05AB1E to do è across my list of lists


Explanation

žKÃ                                    #Filter out non alpha-nums
    Ç48-                               #Convert to ascii and subtract 48 so "0" is 0 etc.
        ©                              #Store that for later
          •...•5в                      #De-compress compressed list 
                 2ä                    #Split into 2 chunks (lines + curves)
                   `                   #Separate them onto the stack 
                    ®                  #Get the value that we stored 
                     èrè               #Apply indexing to both lists
                        ‚              #Put our indexed values back into a list
                         O             #Sum our lists
\$\endgroup\$
  • 1
    \$\begingroup\$ Your output is reversed. It should be line curve, not curve line. \$\endgroup\$ – bigyihsuan Jul 16 at 16:47
  • 1
    \$\begingroup\$ Output can be an array of integers, tuple of integers, comma-separated string, etc. The two numbers must be separate @bigyihsuan they are separate, I don't see what the issue is \$\endgroup\$ – Expired Data Jul 16 at 16:48
  • 1
    \$\begingroup\$ Rules do say Output to STDOUT, or any other output method, the total number of lines and curves contained in the string, in that order. Note the in that order, so line curve. \$\endgroup\$ – bigyihsuan Jul 16 at 16:49
  • 2
    \$\begingroup\$ I would agree with @ExpiredData on this one. Maybe specify in the challenge that the order should be stated in the answer. That would be enough to get by. \$\endgroup\$ – ElPedro Jul 16 at 17:50
  • 1
    \$\begingroup\$ 53 bytes (and with [Line, Curve] as output-order, although that is a coincident and not intentional). \$\endgroup\$ – Kevin Cruijssen Jul 25 at 13:09
5
\$\begingroup\$

Jelly, 45 bytes

ØBċþSḋ“yƘ.ṪñF[)µṡṭɗḌyė$Ṫk“¢⁶KɱzV$QḂḥỵṙu’b5,3¤

A monadic Link accepting a list of characters which yields a list of (two) integers.

Try it online! Or see the test-suite.

How?

ØBċþSḋ“...“...’b5,3¤ - Link: list of characters, T
ØB                   - base-chars = "01...9A...Za...z'
   þ                 - outer product with T using:
  ċ                  -   count occurrences
    S                - sum -> [n(0), n(1), ..., n(9), n(A), ..., n(Z), n(a), ..., n(z)]'
                   ¤ - nilad followed by link(s) as a nilad:
      “...“...’      -   list of two large integers (encoded in base 250)
                5,3  -   five paired with three = [5,3]
               b     -   to base  -> [[Lines(0), Lines(1), ...], Curves(0), Curves(1), ...]
     ḋ               - dot-product
\$\endgroup\$
5
\$\begingroup\$

Scala, 235 bytes

val a=('0'to'9')++('A'to'Z')++('a'to'z')
def f(s:String)=s.filter(a.contains(_)).map(c=>"gdgkdhfckfdlfgedhddgdcedfgkhfcfceeddkgfggglgilddnhfgggfggceegd"(a.indexOf(c))-'a').map(x=>(x%5,x/5)).foldLeft((0,0))((x,y)=>(x._1+y._1,x._2+y._2))

Try it online!

Not so small, probably can be golfed further.
Note: The 52-character string literal is like a dictionary which maps a character to another character which denotes number of lines and curves according to the following table:

Curves|Lines
      |0 1 2 3 4
----------------
     0|a b c d e
     1|f g h i j
     2|k l m n o
\$\endgroup\$
5
\$\begingroup\$

Python 2, 159 154 bytes

For any character lines*4 + curves gives value from 0 to 16. Base-36 is used to encode these values (1 character = 1 value).

-5 bytes thanks to @Chas Brown

lambda s:map(sum,zip(*(divmod(int("5c52c918210000000c615gc9cc5c8gc15291818ggcc00000025155565d6cce915551558gg5c"[ord(x)-48],36),4)for x in s if'/'<x<'{')))

Try it online!

Python 2, 141 bytes

This is a port of my Python3 solution. This version outputs a list of long ints, so it looks like [4L, 2L] instead of [4, 2].

lambda s:map(sum,zip(*(divmod(int("8BK5NLC8RS10XWUX12BG408C2UELUAFEOVARZKCHEEDDMXG09L48ZG",36)/13**(ord(x)-48)%13,3)for x in s if'/'<x<'{')))

Try it online!

\$\endgroup\$
  • 2
    \$\begingroup\$ 154 bytes using base36 and '/'<x<'{' instead of x.isalnum(). \$\endgroup\$ – Chas Brown Jul 17 at 0:28
  • 1
    \$\begingroup\$ @Chas Brown thanks! I was also thinking about '/'<x<'{', but I tried to put it in expression to get rid of if as well. \$\endgroup\$ – Daniil Tutubalin Jul 17 at 0:37
4
\$\begingroup\$

Jelly, 51 bytes

ØBiⱮị“Æƭ&¶*ṪḳAøƬsøD<~²ṂvṠỤṣT3rdʠ¬⁻ÇṆṇ.ÑƑaȮż’b5¤s2¤S

Try it online!

A monadic link that takes a string as input and returns a list of integers as [lines, curves]

\$\endgroup\$
4
\$\begingroup\$

JavaScript (Node.js), 251 219 217 bytes

-34 bytes from @Expired Data :o

_=>_.map(a=>(p+=~~"13103202003101432331324301020202443301011111313332011101124413"[(x=a.charCodeAt()-48)>16?(x-=7)>41?x-=6:x:x])&(o+=~~"10120110210211001001000011211010000021111121120021111111100010"[x]),p=o=0)&&[p,o]

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Retina 0.8.2, 160 bytes

$
¶$`
T`dLl`13103202003101432331324301020202443301011111313332011101124413`^.*
T`dLl`10120110210211001001000011211010000021111121120021111111100010`.*$
.
$*
%`1

Try it online! Link includes test cases. Explanation:

$
¶$`

Duplicate the input string.

T`dLl`13103202003101432331324301020202443301011111313332011101124413`^.*

Count each character's lines on the first line.

T`dLl`10120110210211001001000011211010000021111121120021111111100010`.*$

Count each character's curves on the second line.

.
$*
%`1

Sum the digits separately on each line.

\$\endgroup\$
4
\$\begingroup\$

R, 164 153 bytes

function(s,`!`=utf8ToInt,x=(!"




")[match(!s,c(48:57,65:90,97:122),0)])c(sum(x%%5),sum(x%/%5))

Try it online!

I had the same idea as nimi's answer using a base 5 encoding but encodes as ASCII characters instead of base 16. Uses nomatch = 0 in match to eliminate non-alphanumeric characters.

Returns curves lines.

\$\endgroup\$
4
\$\begingroup\$

Charcoal, 60 bytes

IE⟦”)⊞∧cⅉ→ÞYγμ◧⊞¶u№¶⊘¶∕«⁸””)∨⧴|υ;↷dLτIüO¦:”⟧Σ⭆Φθ№⭆ι⍘ξφλ§ι⍘λφ

Try it online! Link is to verbose version of code. Explanation:

E⟦”)⊞∧cⅉ→ÞYγμ◧⊞¶u№¶⊘¶∕«⁸””)∨⧴|υ;↷dLτIüO¦:”⟧

This is an array of two strings 13103202000101111131333201110112441331014323313243010202024433 and 10120110212111112112002111111110001002110010010000112110100000. The strings are then mapped over.

Φθ№⭆ι⍘ξφλ

The elements of the input are filtered over whether they are contained within the (62) characters of the default base conversion alphabet.

⭆...§ι⍘λφ

The elements that remain are then converted from base (62) and this is then indexed into the mapped string.

I...Σ...

The digits are summed and cast back to string for implicit print.

\$\endgroup\$
4
\$\begingroup\$

Python 3, 165 159 148 146 bytes

For any character (including non-alphanumeric) lines*3 + curves gives value from 0 to 12, so we can use long base-13 number to encode data. To make it shorter it is converted to base-36.

Thanks to @Chas Brown for great advices.

-2 bytes by converting lambda to program.

print(*map(sum,zip(*(divmod(int("8BK5NLC8RS10XWUX12BG408C2UELUAFEOVARZKCHEEDDMXG09L48ZG",36)//13**(ord(x)-48)%13,3)for x in input()if'/'<x<'{'))))

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Python 2, 179 166 165 163 bytes

lambda s:[sum(p[:max(0,p.find(c))].count(',')for c in s)for p in',02BDJPbdefghjpqrtuy,57GLRTVnv,14AFHIKNYZiklmz,EMWXwx',',02569CDGJOPRSUbcdefhinopqrstuy,38BQagjm']

Try it online!

Returns a list [curves, lines].

\$\endgroup\$
3
\$\begingroup\$

Python 2, 525 bytes

l=c=0;e=[(1,1),(3,0),(1,2),(0,2),(3,0),(2,1),(0,1),(2,0),(0,2),(0,1),(3,0),(1,2),(0,1),(1,1),(4,0),(3,0),(2,1),(3,0),(3,0),(1,1),(3,0),(2,0),(4,0),(3,0),(0,1),(1,1),(0,2),(2,1),(0,1),(2,0),(0,1),(2,0),(4,0),(4,0),(3,0),(3,0),(0,2),(1,1),(0,1),(1,1),(1,1),(1,1),(1,2),(1,1),(3,1),(1,2),(3,0),(3,0),(3,2),(2,1),(0,1),(1,1),(1,1),(1,1),(0,1),(1,1),(1,1),(2,0),(4,0),(4,0),(1,1),(3,0)]
d='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
for i in input():
 if i in d:
  p=d.find(i);l+=e[p][0];c+=e[p][1];
print l,c

Try it online!

Similar approach to the reference implementation but somewhat shorter.

\$\endgroup\$
  • 3
    \$\begingroup\$ 283 bytes \$\endgroup\$ – Herman L Jul 16 at 16:13
  • 2
    \$\begingroup\$ Thought about that while I was having a much needed beer in the Biergarten after work but it was too much work to reformat on my handy :) \$\endgroup\$ – ElPedro Jul 16 at 16:26
  • 1
    \$\begingroup\$ @HermanL Feel free to post as your own answer. I have no time to update this eve. \$\endgroup\$ – ElPedro Jul 16 at 18:08
  • 2
    \$\begingroup\$ 265 bytes with a bit more golfing... \$\endgroup\$ – Chas Brown Jul 16 at 23:11
  • 2
    \$\begingroup\$ 231 bytes \$\endgroup\$ – wilkben Jul 17 at 16:03
2
\$\begingroup\$

Perl 5 -MList::Util=sum -p, 180 bytes

say sum y/0-9A-Za-z/13103202003101432331324301020202443301011111313332011101124413/r=~/./g;$_=sum y/0-9A-Za-z/10120110210211001001000011211010000021111121120021111111100010/r=~/./g

Try it online!

\$\endgroup\$
2
\$\begingroup\$

05AB1E, 53 bytes

•xþ¢*>ÌŸÑå#÷AUI'@æýXÁи<¥èå–ΘηžÎà₅åǚĕ5вR2ôžKISk®KèøO

Try it online or verify all test cases.

Explanation:

•xþ¢*>ÌŸÑå#÷AUI'@æýXÁи<¥èå–ΘηžÎà₅åǚĕ
                 '# Compressed integer 101629259357674935528492544214548347273909568347978482331029666966024823518105773925160
 5в               # Converted to base-5 as list: [1,0,2,0,0,2,1,0,1,2,0,3,2,0,1,1,0,3,1,1,0,3,0,3,0,4,0,4,0,2,1,0,0,2,1,0,1,2,2,0,1,1,1,0,0,3,0,4,0,2,0,3,1,1,0,3,0,3,1,2,0,3,0,4,1,1,1,0,2,1,0,3,0,3,1,1,0,4,0,4,0,2,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,2,2,3,0,3,0,3,2,1,1,3,1,1,2,1,1,1,1,1,1,1,1,0,1,1,2,0]
   R              # Reverse this list (due to the leading 0)
    2ô            # Split it into pairs: [[0,2],[1,1],[0,1],[1,1],[1,1],[1,1],[1,2],[1,1],[3,1],[1,2],[3,0],[3,0],[3,2],[2,1],[0,1],[1,1],[1,1],[1,1],[0,1],[1,1],[1,1],[2,0],[4,0],[4,0],[1,1],[3,0],[3,0],[1,2],[0,1],[1,1],[4,0],[3,0],[2,1],[3,0],[3,0],[1,1],[3,0],[2,0],[4,0],[3,0],[0,1],[1,1],[0,2],[2,1],[0,1],[2,0],[0,1],[2,0],[4,0],[4,0],[3,0],[3,0],[1,1],[3,0],[1,1],[0,2],[3,0],[2,1],[0,1],[2,0],[0,2],[0,1]]
      žK          # Push builtin string "abc...xyzABC...XYZ012...789"
        IS        # Push the input, split into characters
          k       # Get the index of each of these characters in the builtin-string
           ®K     # Remove all -1 for non-alphanumeric characters that were present
             è    # Use these indices to index into the earlier created pair-list
              ø   # Zip/transpose; swapping rows/columns
               O  # Sum both inner lists
                  # (after which the result is output implicitly)

See this 05AB1E tip of mine (sections How to compress large integers? and How to compress integer lists?) to understand why •xþ¢*>ÌŸÑå#÷AUI'@æýXÁи<¥èå–ΘηžÎà₅åǚĕ is 101629259357674935528492544214548347273909568347978482331029666966024823518105773925160 and •xþ¢*>ÌŸÑå#÷AUI'@æýXÁи<¥èå–ΘηžÎà₅åǚĕ5в is [1,0,2,0,0,2,1,0,1,2,0,3,2,0,1,1,0,3,1,1,0,3,0,3,0,4,0,4,0,2,1,0,0,2,1,0,1,2,2,0,1,1,1,0,0,3,0,4,0,2,0,3,1,1,0,3,0,3,1,2,0,3,0,4,1,1,1,0,2,1,0,3,0,3,1,1,0,4,0,4,0,2,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,2,2,3,0,3,0,3,2,1,1,3,1,1,2,1,1,1,1,1,1,1,1,0,1,1,2,0].

\$\endgroup\$
1
\$\begingroup\$

Python 3, 697 bytes

def f(s):
    l=0;c=0;d={'0':(1,1),'1':(3,0),'2':(1,2),'3':(0,2),'4':(3,0),'5':(2,1),'6':(0,1),'7':(2,0),'8':(0,2),'9':(0,1),'A':(3,0),'B':(1,2),'C':(0,1),'D':(1,1),'E':(4,0),'F':(3,0),'G':(2,1),'H':(3,0),'J':(1,1),'K':(3,0),'L':(2,0),'M':(4,0),'N':(3,0),'O':(0,1),'P':(1,1),'Q':(0,2),'R':(2,1),'S':(0,1),'T':(2,0),'U':(0,1),'V':(2,0),'W':(4,0),'X':(4,0),'Y':(3,0),'Z':(3,0),'a':(0,2),'b':(1,1),'c':(0,1),'d':(1,1),'e':(1,1),'f':(1,1),'g':(1,2),'h':(1,1),'i':(3,1),'j':(1,2),'k':(3,0),'l':(3,0),'m':(3,2),'n':(2,1),'o':(0,1),'p':(1,1),'q':(1,1),'r':(1,1),'s':(0,1),'t':(1,1),'u':(1,1),'v':(2,0),'w':(4,0),'x':(4,0),'y':(1,1),'z':(3,0)};
    for i in s:
        if i in d:
            l+=d[i][0];c+=d[i][1];
    return l,c

A simple first attempt. I put the table into a dictionary, looped through the string, incremented some counters, and returned a tuple. Input is a string.

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Why non competing? Looks fine to me. \$\endgroup\$ – ElPedro Jul 16 at 16:42
  • 1
    \$\begingroup\$ Why the downvote without a comment? \$\endgroup\$ – ElPedro Jul 16 at 18:09
1
\$\begingroup\$

C# (Visual C# Interactive Compiler), 157 bytes

x=>(x=x.Where(n=>n<123&n>47)).Sum(n=>p[n-48]/5)+" "+x.Sum(n=>p[n-48]%5);var p=@"




";

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.