Significant Whitespace

55

5

We define whitespace to be any of the three characters, tab (0x09), newline (0x0A) or space (0x20).

For this challenge, you're to write two programs or functions in the same programming language, which perform the following tasks:

  1. Count the whitespace characters in a given string. For instance, the input

      123 -_-   abc
    def
    

    would return 7 (provided there is no trailing newline).

  2. Split a given string at consecutive runs of whitespace. If the string starts or ends with whitespace, no empty strings should be returned at the ends. For instance, the same input

      123 -_-   abc
    def
    

    would return ["123", "-_-", "abc", "def"].

In either case you may take input via STDIN, command-line argument or function argument a return the result or print it STDOUT. For the second program, if you choose to print to STDOUT, please print each string on its own line, without surrounding quotes.

For both programs you may assume that the input contains only printable ASCII (0x20 to 0x7E) and whitespace.

Now here is the catch:

  • If all whitespace is removed from both programs/functions, the resulting strings have to be identical. That is, your two submissions may only differ in the number and placement of whitespace characters.
  • Neither program/function may contain any string or regex literals (character literals are fine, provided your language has a designated character type).
  • Neither program/function may contain any comments.
  • You must not read the program's source code, directly or indirectly.

This is code golf. Your score is the sum of the sizes of both solutions (in bytes). Lowest score wins.

Leaderboards

The following Stack Snippet generates both a regular leaderboard and an overview of winners by language. So even if your language of choice doesn't let you win the entire challenge, why not try to snatch a spot on the second list? I'd be very interested to see how people tackle this challenge in a variety of languages!

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

# Language Name, N bytes

where N is the total size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

# Ruby, <s>104</s> <s>101</s> 96 bytes

You may also include the individual counts before the total count, e.g.

# Python 2, 35 + 41 = 76 bytes

The last number that is not struck through will be used by the snippet.

<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script><script>site = 'meta.codegolf',postID = 5314,isAnswer = true,QUESTION_ID = 42253;jQuery(function(){var u='https://api.stackexchange.com/2.2/';if(isAnswer)u+='answers/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJeRCD';else u+='questions/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJO6t)';jQuery.get(u,function(b){function d(s){return jQuery('<textarea>').html(s).text()};function r(l){return new RegExp('<pre class="snippet-code-'+l+'\\b[^>]*><code>([\\s\\S]*?)<\\/code><\/pre>')};b=b.items[0].body;var j=r('js').exec(b),c=r('css').exec(b),h=r('html').exec(b);if(c!==null)jQuery('head').append(jQuery('<style>').text(d(c[1])));if (h!==null)jQuery('body').append(d(h[1]));if(j!==null)jQuery('body').append(jQuery('<script>').text(d(j[1])))})})</script>

Martin Ender

Posted 2014-12-09T15:58:24.670

Reputation: 184 808

1So what in Bash count as string literals? – jimmy23013 – 2014-12-22T11:08:31.043

@user23013 As far as I'm aware, string literals in Bash can only include whitespace if they are surrounded in quotes, right? If so, then it would be "in the spirit of the law" to disallow only quoted string literals. (The idea behind disallowing string literals is to avoid some simple solutions, where you just include a space in a string and switch the behaviour depending on the length of the string.) – Martin Ender – 2014-12-22T11:18:58.817

The snippet is not listing the rankings :( – sergiol – 2017-07-21T23:40:39.593

26That leaderboard is cool! – Digital Trauma – 2014-12-09T19:56:51.113

5Sounds like any Whitespace answer would comply with rule 1. ;) – nyuszika7h – 2014-12-10T14:31:32.583

1@nyuszika7h Indeed it would, but it won't be particularly short anyway. – Martin Ender – 2014-12-10T14:32:32.563

7Significant whitespace, so not whitespace with benefits or anything... – corsiKa – 2014-12-10T19:23:08.053

Answers

15

Pyth, 16 + 15 = 31 bytes

Try it here.

Counter:

L@,cb)sm!cd)b1 0

Splitter:

L@,cb)sm!cd)b10

These each define a function, y, which takes a string input to solve the desired task.

Thanks to @FryAmTheEggman for the idea of using Pyth's feature of modular indexing into lists to shave a character.

Test cases:

L@,cb)sm!cd)b1 0y++"abc def"b"gh ij k"
L@,cb)sm!cd)b10y++"abc def"b"gh ij k"

Explanation:

L                  define a function, y, which takes one input, b.
 @                 Index into
  ,                2-tuple of
   cb)             b.split()                          (solution to splitter)
   s               sum over                           (solution to counter)
    m              map, with input d, to
     !cd)          logical negation of d.split()      (empty list is falsy)
     b             over b.
                   Index is either:
   10
   1
                   Indexing is modulo the length of the list in Pyth.
 0                 In one case, a 0 with a leading space is outside the function.
                   Leading space suppresses print, so the 0 is invisible.

isaacg

Posted 2014-12-09T15:58:24.670

Reputation: 39 268

52

Python, 54 + 56 = 110 bytes

Counter:

m=lambda x:sum(y.isspace()for y in x)
+1
0<9or x.split()

Splitter:

m=lambda x:sum(y.isspace()for y in x)+10<9or x.split()

For the counter, we use the fact that Python is okay with having just an expression on a line. It's necessary to split up +1 and 0<9or x.split() to stop a NameError from being thrown, as 0<9 being True prevents x.split() from being evaluated due to short circuiting.

For the splitter, since the number of whitespace is always nonnegative, sum(y.isspace()for y in x)+10<9 is always False and the splitting function comes into play.


Alternative 1, 59 + 60 = 119 bytes

Counter:

m=lambda x:[x.split(),sum(y.isspace()for y in x)][min([1])]

Splitter:

m=lambda x:[x.split(),sum(y.isspace()for y in x)][m in([1])]

The results of both counting and splitting are stored in a two-element list. The list is indexed by either min([1]), returning the minimum of the one-element list containing 1, or m in([1]), which returns False (equivalent to 0) as m is not contained in [1].


Alternative 2, 67 + 69 = 136 bytes

Counter:

ted=1;s=lambda x:[x.split(),sum(y.isspace()for y in x)][not s or ted]

Splitter:

ted=1;s=lambda x:[x.split(),sum(y.isspace()for y in x)][not sorted]

Like above, the results of both counting and splitting are stored in a two-element list. sorted is a built-in function which is a truthy value, so not sorted returns False (equivalent to 0). For not s or ted, since s is a function and also truthy, not s is False and ted = 1 is returned.


Alternative 3, 59 + 60 = 119 bytes

Counter:

def f(s):a=s.split();a1=len(s)-len((s*0).join(a));return a1

Splitter:

def f(s):a=s.split();a1=len(s)-len((s*0).join(a));return a
1

This is a function where splitter's result is stored in the variable a, and counter's result is stored in the variable a1. Like before, Python is fine with having just an expression on a line, in this case 1. Splitting up a1 determines what to return from the function.

Sp3000

Posted 2014-12-09T15:58:24.670

Reputation: 58 729

sum(map(str.isspace,x)) is shorter by three characters! That would make your score 104 :) – James Elegan – 2014-12-15T23:54:25.773

@JamesElegan I saw it in feersum's answer but decided not to put it in because it's not going to win anyway :P – Sp3000 – 2014-12-16T00:03:16.363

22I'd +1 again for not sorted. – Martin Ender – 2014-12-09T17:02:19.570

Is the newline between +1 and 0<9or x.split() needed? – isaacg – 2014-12-09T20:26:00.050

1@isaacg If you care about exceptions, then yes – Sp3000 – 2014-12-09T20:28:31.173

You can shave off 3 bytes with m=lambda x:sum(y.isspace()for y in x)+00and x.split() and m=lambda x:sum(y.isspace()for y in x)+0;0and x.split() (making that semicolon a newline of course) – cjfaure – 2014-12-11T18:14:25.220

@cjfaure I don't think the first one works as a splitter if there's no whitespace – Sp3000 – 2014-12-11T18:19:19.950

@Sp3000 Oh yeah, if there's nothing at all it just returns 0. :c – cjfaure – 2014-12-11T18:22:46.200

16

Java 8, 239 + 240 = 479

Count the whitespace (returns Integer)

Object f(String s){String r=new String(new char[]{92,'s'}),e=new String();int intx=0;intx=1;return intx>0?s.chars().filter(c->c==9|c==10|c==32).count():java.util.Arrays.stream(s.split(r)).map(t->t.replaceAll(r,e)).filter(t->t.length()>0);}

Split on the whitespace (returns Stream<String>)

Object f(String s){String r=new String(new char[]{92,'s'}),e=new String();int intx=0;int x=1;return intx>0?s.chars().filter(c->c==9|c==10|c==32).count():java.util.Arrays.stream(s.split(r)).map(t->t.replaceAll(r,e)).filter(t->t.length()>0);}

Explanation:

Object f(String s){
    String r=new String(new char[]{92,'s'}),e=new String();  // init regex'es

    int intx=0;     // critical variable

    intx=1;         // change intx to 1
              OR
    int x=1;        // new, unused variable

    return intx>0 ? // test variable to decide what to do
      s.chars().filter(c->c==9|c==10|c==32).count() :
      java.util.Arrays.stream(s.split(r)).map(t->t.replaceAll(r,e)).filter(t->t.length()>0);
}

Ypnypn

Posted 2014-12-09T15:58:24.670

Reputation: 10 485

Pretty good, considering that Java has to be the worst language for code golfing. – tbodt – 2014-12-13T04:38:27.193

To me, this looks brilliant. +1 – Rodolfo Dias – 2014-12-11T11:20:20.777

13

Whitespace, 75 + 153 = 228

Spaces, tabs and newlines substituted by STL, respectively, and folded for legibility. Convert to a proper Whitespace file with tr -d \\n | sed 'y/STL/ \t\n/'.

Counter

SSSLLSSLSSSTSSSSSLSLSSLSTLTSTTTSLSLTSSLTSSTLTTLSSSTLTSSSLSLLLSSSLS
LLSLLTLST

Splitter

SSSTLSSSLTTSLSSTLSSSLSLSTLTSTTTSLSSLSLTSLSSSTSSSSTLTSSTLTTTTLSSSTL
SLSTTSLSLSLLSSTTLSSSTSTSLSSSTLTTTLTSTSLTLSSSSSTLSSSLTTSLSSTSLLSLTL
LSSSLTLSSLSLTLLSSLLLL

ninjalj

Posted 2014-12-09T15:58:24.670

Reputation: 3 018

2I was wondering how long it would take... ;) – Martin Ender – 2014-12-12T02:08:00.767

4With whitespace, this becomes two separate code golfing challenges. – tbodt – 2014-12-13T04:51:03.950

13

Marbelous, 103 + 92 = 195

Counter:

@0      @200@1@3
]]&1]]3W
  \\!!?001
        &0  >W@1
>W    @2/\  /\@3+A
00&0      &1
          Dp
@0//

Splitter:

@0  @200@1    @3
]]&1]]  3W    \\
  !!    ?001&0
>W@1>W@2
/\  /\@3+A00&0
          &1Dp@0
//

Test these programs here. Cylindrical Boards, Include Libraries, and spaces for blank cells must all be checked.

Input and Output are through STDIN/STDOUT.

Explanation

Counter:

Counter Source

The blue path receives input. If the character is a whitespace character (ascii value less than 0x21), the black path is taken, which synchronizes with the purple path.

The purple path simply increments a marble stored in the &1 synchronizer each time the black path is taken.

Once there is no more input, the red path is taken, printing the number of whitespace characters and exiting.

Splitter:

Splitter Source

The program begins with the blue path, which loops until a non-whitespace character is found.

Once a non-whitespace character is retrieved, the black path is taken, which prints out this character and moves execution to the green path, which loops and prints until a whitespace-character is received. Execution then continues to the purple path, which contains 3W, or a three-way splitter.

The left branch moves execution to the blue path (and whitespace is discarded until a non-whitespace character is found).

The middle branch sets the copy of the input to 0 with ?0 (generate a random number between 0 and 0), and adds 10 (0x0A = newline), which is then outputted.

The right path is discarded.

es1024

Posted 2014-12-09T15:58:24.670

Reputation: 8 953

It seems like the splitter doesn't terminate if there's trailing whitespace. – Martin Ender – 2014-12-13T09:11:08.077

12

CJam, 26 + 27 = 53 59 61 73 77 bytes

Counter

'!q_,\SN9c++SerS%:Qs,-QN*?

Splitter

' !q_,\SN9c++SerS%:Qs,-QN*?

How it works

The idea is simple, calculate both number of whitespaces and split the string on consecutive runs of whitespaces. Then choose one of them based on the following fact that ' ! means not of space character which is falsy, while '! is the ! character, which is truthy.

Expanded code:

'! / ' !                              "Get truthy or falsy value";
        q_                            "Read the input, make a copy";
          ,\                          "Take the length of the copy and swap";
            SN9c++                    "Get a string comprised of all Whitespaces";
                  Ser                 "Replace any occurrence of any character of"
                                      "the above string with space";
                     S%               "Split on one or more runs of space";
                       :Qs,           "Store this in Q, flatten to a string and take length";
                           -          "Subtract from total length to get count";
                            QN*       "Put the splitted array on stack and join newline";
                               ?      "Base on the truthy or falsy value, pick one to print";

Input is from STDIN and output is to STDOUT

Try it online here

Optimizer

Posted 2014-12-09T15:58:24.670

Reputation: 25 836

10

Mathematica, 44 + 43 = 87 97 bytes

I thought I'd add another language to the mix.

Counter:

StringCount[#,Whitespace]+0 1StringSpli t@#&

Splitter:

String Count[#,Whitespace]+01StringSplit@#&

This makes use of Mathematica's feature that space separation is the same as multiplication. And that multiplying something with 0 is always 0, and adding 0 to something is always idempotent.

For the counter, we first count the whitespace, and the we add 0*1*StringSpli*t@#. StringSpli and t aren't defined, but Mathematica uses symbolic computation, so it just treats those as an unknown variable and function. The 1* is idempotent (just as 0+), the 0* turns it into a zero. It is necessary to separate the StringSplit into two variables, because 0 times a list is treated as a scalar-vector multiplication which results in a vector (list) of zeroes.

For the splitter, I'm using the fact that Count also exists but doesn't look into strings. It tries to count all subexpressions matching the pattern, but Whitespace is a pattern that only applies to string contents. So Count will always return 0, which makes the String vanish. The multiplication of the split array by 01 = 1 is again idempotent.

Martin Ender

Posted 2014-12-09T15:58:24.670

Reputation: 184 808

10

Ruby, 107 91 bytes

Splitter (46 bytes)

p
p=gets(p).split
puts p||$_.size-pp.join.size

Counter (45 bytes)

pp=gets(p).split
puts p||$_.size-pp.join.size

p is a predefined method that, with no arguments, just returns nil. We use this in several ways. In the splitter, the initial p does nothing. gets(p) reads in everything from standard input, since the delimiter is null. We call the built-in split method on that, and assign the result to p, so now when it's not given arguments it'll be parsed as a variable. puts p||... short-circuits and prints each element of the p variable to its own line.

In the counter, we delete the first newline so that the split array is assigned to pp instead. Since we haven't assigned to p, it's still the nil-returning method so the second part of the || gets evaluated and passed to puts. $_ is a magic variable containing the result of gets, so the total amount of whitespace is the size of that minus the non-whitespace characters, which are what pp contains. I feel like there should be a shorter way of doing the counting, but I can't find one, and at any rate using the split array in the counter is fun.

histocrat

Posted 2014-12-09T15:58:24.670

Reputation: 20 600

7

Python, 169

It's almost too easy to do this in Python!

Counter:

def x(s):
 def y(s):
  return sum(map(str.isspace,s))
  return s.split()
 return y(s)

Splitter:

def x(s):
 def y(s):
  return sum(map(str.isspace,s))
 return s.split()
 return y(s)

They differ in only one space, and I'm not doing any trickery like splitting a number or a variable name in half :)

James Elegan

Posted 2014-12-09T15:58:24.670

Reputation: 171

6

C, 138+136 = 274

In each case, the code is a program that accepts exactly one command-line argument and prints the result to stdout. \t should be replaced with a tab character. If you want to pass an argument containing tabs and newlines, it's your job to figure out how ;).

Counting

#define strtok strpbrk
h=' \t\n';main(c,v,n)char**v;{for(n=- -c-1;v[n]=strtok(1[v],&h);n[v]++)v[!n]=0,puts(*v),c++;n*='d%';printf(&n,c-2);}

Splitting

#define strtokstrpbrk
h=' \t\n';main(c,v,n)char**v;{for(n=--c-1;v[n]=strtok(1[v],&h);n[v]++)v[!n]=0,puts(*v),c++;n*='d%';printf(&n,c-2);}

feersum

Posted 2014-12-09T15:58:24.670

Reputation: 29 566

6

JavaScript, 95 + 96 = 191 bytes

Counter:

c=(a,v)=>{v
v=a=a.split(RegExp(String.fromCharCode(92,115)));return v?a.length-1:a.filter(j=>j)}

Splitter:

s=(a,v)=>{vv=a=a.split(RegExp(String.fromCharCode(92,115)));return v?a.length-1:a.filter(j=>!!j)}

Ungolfed:

s=(a,v)=>{

    v  // this `v` is ignored, or combined with the next line to make `vv`

    // split array and store it in `a` and `v` (or alternatively `vv`)
    v = a = a.split(RegExp(String.fromCharCode(92,115)));

    return v?
            a.length-1        // return number of whitespace chars
            :
            a.filter(j=>j)    // return array without empty strings
    }

The RegExp(String.fromCharCode(92,115) line creates the whitespace-matching regex /\s/ without regex or string literals.

In each program, we use the variable v or vv. We store the split array into that variable (v or vv), and then branch our behavior on the value of v (meanwhile, vv is ignored). In the counter, v has a truthy value; in the splitter it has a falsy value (because vv got the value instead).


Alternate: JavaScript, 250 bytes

I have another solution that isn't winning any prizes for brevity, but I thought it was an interesting challenge to abuse JavaScript's automatic semicolon insertion behavior.

Counter:

c=a=>{a=a.split(RegExp(String.fromCharCode(92,115)));x:for(i=2;i--;)for(o=i?a.length-1:a.filter(j=>j);1;){break x}return o}

Splitter:

s=a=>{a=a.split(RegExp(String.fromCharCode(92,115)));x:for(i=2;i--;)for(o=i?a.length-1:a.filter(j=>j);1;){break
x}return o}

Ungolfed counter:

s=a=>{
    a = a.split(
            RegExp(String.fromCharCode(92,115))   // split input on whitespace regex /\s/
        );  
    x:                             // x is a label for the outer loop
    for(i=2;i--;)                  // run this outer loop twice
        for(o=i?                   // if this is the first outer loop pass, 
               a.length-1          //    set `o` to number of whitespaces
               :                   // else, on second outer loop pass,
               a.filter(j=>j);     //    set `o` to split input (w/o empty strings)
            1;                     // 1 is truthy; run inner loop forever
            ) {
                break x;           // break out of outer loop
            }
    return o;                      // return `o`
}

The splitter is exactly the same, except for the line:

break x;

is now

break
x;

JavaScript's automatic semicolon insertion normally does not terminate multi-line statements early if they can be understood without a line break, but it does not tolerate line breaks after return, continue or break. Therefore, the line is read simply as break, which breaks out of the inner loop only, instead of breaking out of the outer loop. The "second-pass" behavior o = a.filter(j=>j) is then executed (versus being skipped in the counter), because the outer loop is given a second pass.

apsillers

Posted 2014-12-09T15:58:24.670

Reputation: 3 632

Is !!x different to the auto Bool convert? – l4m2 – 2018-03-31T13:24:25.560

@l4m2 It is not! I have removed it, since filter auto-bools its callback return by the same rules as !!. Thanks! – apsillers – 2018-03-31T17:26:43.753

5

Python, 228 198 182 166 146 145 bytes

Counter (72 bytes):

ior1=0
w=lambda i:i.split()if ior1 else sum(ord(c)in(9,10,32)for c in i)

Splitter (73 bytes):

ior1=0
w=lambda i:i.split()if i or 1else sum(ord(c)in(9,10,32)for c in i)

ior1 is a falsey variable, but i or 1 is truthy. That's the main trick.

undergroundmonorail

Posted 2014-12-09T15:58:24.670

Reputation: 5 897

Doesn't this break if i is the empty string for the splitter? Could be fixed by changing iorb to ior1, which also lets you save the character between 1 and else. – isaacg – 2014-12-09T23:56:38.813

@isaacg I totally forgot that you could have numbers in variable names! Thank you <3 – undergroundmonorail – 2014-12-10T13:17:54.537

5

Befunge 98, 61 + 59 = 120

Counter:

~:'!-0`#v_ >$1+#@ #. #
 @#,#$ #<_v#`0-!':~ # .#
  ,#$ #+55<v

Splitter:

~:'!-0`#v_ >$1+#@ #.#
 @#, #$#<_v#`0-!':~ #.#
  , #$#+55<v

ninjalj

Posted 2014-12-09T15:58:24.670

Reputation: 3 018

4

Bash, 75 + 79 = 154 bytes

This relies on bash being able to continue execution even if some lines or parts of a line of the script are malformed (in some circumstances). Whitespace is used to deactivate escapes for some close brackets, and to break a pipe by putting it on a new line.

Splitter:

echo $((`echo $1|wc -w`+${#1}-$(\)\)\)
for a in $1;do echo $a;done|wc -c)))

Counter:

echo $((`echo $1|wc -w`+${#1}-$(\ )\ )\ )
for a in $1;do echo $a;done
|wc -c)))

Input is via commandline argument, output is via stdout.

Because this relies on bash error behaviour, the user is expected to ignore stderr.

Example run (showing input with a newline and multiple contiguous spaces):

# bash counter.sh "abc def
gh   ij k" 2>/dev/null
6
# bash splitter.sh "abc def
gh   ij k" 2>/dev/null
abc
def
gh
ij
k

Riot

Posted 2014-12-09T15:58:24.670

Reputation: 4 639

4

Ruby, 114 + 116 107 + 109 = 216 bytes

This can't compete with the ruby solution by histocrat, but I thought it would be worth putting up anyway.

I used $z for nil and nil.to_s for String.new

The extra whitespace character that I add to the end of the input is to force the last word to be added to the array (r) - a word is only added to the end of the array when a whitespace character follows a non-whitespace character. The alternative was adding another r<<w if w after the each_byte block.

Counting

->s{r=[]
n=-1
w=$z
(s+9.chr).each_byte{|b|if b<33
r<<w if w
w=$z
n+=1
else
w=w.to_s+b.chr
end}
$zorr ?r:n}

Splitting

->s{r=[]
n=-1
w=$z
(s+9.chr).each_byte{|b|if b<33
r<<w if w
w=$z
n+=1
else
w=w.to_s+b.chr
end}
$z or r ?r:n}

alexanderbird

Posted 2014-12-09T15:58:24.670

Reputation: 251

Ah, I wasn't sure about the ruling on that one. I've changed it to use if-else instead of the ternary operator - no more string literals. – alexanderbird – 2014-12-13T09:47:06.830

3

Haskell, 53 + 55 = 108 36 + 38 = 74 bytes

Counter

f=do
 pure(length.filter(<'!'))words

Splitter

f=do
 pure(length.filter(<'!'))
 words

This solution makes use of the fact that in Haskell functions are an instance of the Monad type class and thus can be used as monadic actions in do-notation.

In the first case the resulting function of the do-block is the first argument of pure (which is essentially const for the function type), making the counter the final result and the splitter being discarded.

In the second case pure is only applied to a single argument, making it a function that returns another function (the counter). However, the result is never used and thus discarded. The final result is the second line of the do-block, the splitter.

siracusa

Posted 2014-12-09T15:58:24.670

Reputation: 623

Nice approach! [' ','\t','\n'] can be shortened to " \t\n". – Laikoni – 2018-03-31T09:11:20.340

@Laikoni The description only allows character literals, no string or regex literals – siracusa – 2018-03-31T14:09:58.697

2Because the challenge doesn't require you to handle most control characters, you can shorten this by using (<'!') to test for whitespace. – Ørjan Johansen – 2019-09-21T05:32:29.647

2

Java 8, 187 + 188 = 375

First of all, I'd like to say that this answer is heavily based on @Ypnypn's. I basically replaced some parts with shorter ones (including the whitespace-dependent part, which IMO is the most important in this challenge), but the functional code is mostly the same.

Count the whitespace, 187 (returns int):

Object f(String s){String r=new String(new char[]{92,115});int a=0;return a--+a>0?s.chars().filter(c->c>8&c<11|c==32).count():java.util.Arrays.stream(s.split(r)).filter(t->t.length()>0);}

Split on the whitespace, 188 (returns Stream<String>):

Object f(String s){String r=new String(new char[]{92,115});int a=0;return a- -+a>0?s.chars().filter(c->c>8&c<11|c==32).count():java.util.Arrays.stream(s.split(r)).filter(t->t.length()>0);}

PurkkaKoodari

Posted 2014-12-09T15:58:24.670

Reputation: 16 699

2

J, 48 + 49 = 97 char

Two functions taking and returning a single argument. Used the crappiest way that I could think of to beat the same-but-whitespace rule, so there are probably characters to be saved by finding a more clever route around that.

(aa[aa=.+/@a=.a:-.~(e.u:)&9 10 32 :(<;._1~1,}.))      NB. count
(a a[aa=.+/@a=.a:-.~(e.u:)&9 10 32 :(<;._1~1,}.))     NB. split

We define the verb a to have two different actions, depending on whether it's used with one argument or with two. With one argument, it is (e.u:)&9 10 32, which checks if each character is whitespace or not. With two arguments, it is a:-.~(<;._1~1,}.), which takes a boolean vector on the right and cuts the left argument at those positions, throwing out any empty cuts with a:-.~.

Then, we define aa to be number of True values in the result of a, which only makes sense with one argument. Finally, we use aa or a a depending on whether we want to count or split the whitespace of the string. aa works as expected.

The reason a a works is because when J sees (f g)y, it considers (f g) a hook and evaluates it like y f (g y). In this case, f is the dyadic a above which does the cutting, and g is a[aa, which calculates the sum from aa, throws it out, and calculates (monadic) a again.

At the REPL:

   (aa[aa=.+/@a=.a:-.~e.&(u:9 10 32) :(<;._1~1,}.))   '  123',TAB,'-_-   abc',LF,'def'
7
   (a a[aa=.+/@a=.a:-.~e.&(u:9 10 32) :(<;._1~1,}.))  '  123',TAB,'-_-   abc',LF,'def'
+---+---+---+---+
|123|-_-|abc|def|
+---+---+---+---+

algorithmshark

Posted 2014-12-09T15:58:24.670

Reputation: 8 144

2

Bash, 54 + 50 = 104 bytes

Counter

a=$IFS
IFS=
cat()(tr -cd $a|wc -c)
printf %s \\n$1|cat

Splitter

a=$IFSIFS=ca
t()(tr-cd$a|wc-c)
printf %s\\n $1|cat

jimmy23013

Posted 2014-12-09T15:58:24.670

Reputation: 34 042

1

Perl 6, 31 + 32 = 63 bytes

Counter

{?^1??.words!!+grep 33>*,.ords}

Try it online!

?^1 is parsed like ?^ 1 which applies the Boolean negation operator to 1, resulting in False.

Splitter

{? ^1??.words!!+grep 33>*,.ords}

Try it online!

? ^1 converts the range 0..0 to Bool, resulting in True.

nwellnhof

Posted 2014-12-09T15:58:24.670

Reputation: 10 037

1

Perl, 37 + 38 = 75

Counter:

sub f{($_)=@_;(y/   - //,[split])[0.1]}

Splitter:

sub f{($_)=@_;(y/   - //,[split])[0 .1]}

ninjalj

Posted 2014-12-09T15:58:24.670

Reputation: 3 018

0

C (gcc), 88 + 89 = 177 bytes

Splitter

i,n,x,c;f(char*s){x=n=i=0;for(x+++n;c=*s++;c*x&&putchar(c))i=c<33?n++,c=i*10,0:1;x=n-1;}

Splitter

Counter

i,n,x,c;f(char*s){x=n=i=0;for(x+ ++n;c=*s++;c*x&&putchar(c))i=c<33?n++,c=i*10,0:1;x=n-1;}

Counter

Rundown

Takes input as a function argument. The counting function returns the number of whitespace. The splitting function uses STDOUT for its output (but incidentally returns number of whitespace minus one as well).

i,                      Flag signalling whether we are inside a word.
n,                      Number of whitespace encountered.
x,                      Flag signalling whether or not we should output the words.
c;                      Current character.
f(char*s){              Take input string as an argument.
x=n=i=0;for(            Initialise everything and start loop.
x+++n;                  SPLITTER ONLY: Interpreted as x++ +n, meaning x is set to 1 and n stays 0.
x+ ++n;                 COUNTER ONLY: Inverse of the above. Sets n to 1, and x stays 0.
c=*s++;                 Sets c to current char and increment string pointer, end loop if end of string.
c*x&&putchar(c))        Only output c if x is 1 and c is non-zero, which only happens if we left a word.
i=c<33?                 Since input contains only printable ASCII or whitespace, anything below 33 is whitespace.
       n++,             ...if that is the case, increment the whitespace counter (n)
           c=i*10,      ...and set c to newline (10), but only if we just left a word (if i is 1)
                  0:    ...and set i to 0.
                    1;  If not a whitespace, set i to 1, signalling we are inside a word.
x=n-1;}                 Implicitly returns n-1, which is the number of whitespaces if we are in the counter function.

gastropner

Posted 2014-12-09T15:58:24.670

Reputation: 3 264

0

Zsh, 35+35=70 bytes

  • Neither program/function may contain any string or regex literals

I am unsure whether [^$IFS] qualifies, since it is used in pattern matching. Here is a 45+45 solution in the case it is banned.


Split:

:<<<${#1//[^$IFS]} 
:
<<<${(F)${=1}}

Count:

:
<<<${#1//[^$IFS]}
:<<<${(F)${=1}}

The : builtin is equivilent to true, we use it as something between a comment and /dev/null (since comments are disallowed) by piping the unwanted expansion to it.

Zsh has a builtin for splitting on whitespace, that being ${=var}. This makes it hard to do any kind of logical combination other than just executing both and discarding the one we don't want.

Try it online!

GammaFunction

Posted 2014-12-09T15:58:24.670

Reputation: 2 838

0

Python 2, 98

Splitting (49)

Returns the tokens in a list.

f=lambda s:[sum(map(str.isspace,s))]and s.split()

Counting (49)

Returns a list of length one containing the number of space characters. It will most likely cause a runtime error, but the function f can be used after executing the code.

f=lambda s:[sum(map(str.isspace,s))]
ands.split()

feersum

Posted 2014-12-09T15:58:24.670

Reputation: 29 566