To neutralize data, recursively replace all numbers (not digits!) with zeros and all characters (not strings!) with spaces.

You must accept any structure of mixed numeric/character data that your language can handle. For example, you must accept actual strings (and not restrict your input to lists of single characters) if your language can handle such.

If your language contains a built-in which does all or most of this task, I would appreciate an additional alternative version without it.

The shortest submission in each language is a winner, and will receive an upvote from me.

Sample cases

  1. """"

  2. 70

  3. 123.4560

  4. "X"" "

  5. " "" "

  6. "Yo!"" "

  7. [][]

  8. [-1.2E3][0]

  9. ["Hey"][" "]

  10. ["H","e","y"][" "," "," "]

  11. ["R",2,"D",2][" ",0," ",0]

  12. ["C","3","P",0][" "," "," ",0]

  13. ["THX",[1138]][" ",[0]]

  14. ["T","H","X",[1138]][" "," "," ",[0]]

  15. [[["H"],"e",1,1,0],[[-3],"arth"]][[[" "]," ",0,0,0],[[0]," "]]

share|improve this question
    
What if our language doesn't distinguish between characters and length-1 strings? – xnor 6 hours ago
    
@xnor AFAICT the effect would be the same. – Adám 6 hours ago
    
Oh, I see that now from the test cases, but it wasn't clear to me that meant to take every string element and replace each of its characters with spaces. Actually, I didn't interpret that the replacements have to be done recursively at all. The spec talks about neutralizing an array, but it looks like you want single elements not in an array to be acted on as well? – xnor 6 hours ago
    
@xnor Correct. Feel free to edit the question to better reflect this. – Adám 6 hours ago
    
Let us continue this discussion in chat. – Adám 5 hours ago

JavaScript (ES6), 53 47 bytes

f=o=>o.big?o.replace(/./g,' '):o.map?o.map(f):0

Test cases

f=o=>o.big?o.replace(/./g,' '):o.map?o.map(f):0

test = [
  "",
  7,
  123.456,
  "X",
  "  ",
  "Yo!",
  [],
  [-1.2E3],
  ["Hey"],
  ["H","e","y"],
  ["R",2,"D",2],
  ["C","3","P",0],
  ["THX",[1138]],
  ["T","H","X",[1138]],
  [[["H"],"e",1,1,0],[[-3],"arth"]]
];

test.map(o => {
  console.log(JSON.stringify(o), '=>', JSON.stringify(f(o)));
});

share|improve this answer

Ruby, 54 53 bytes

f=->a{a.map{|x|x*0==0?0:x*0==""?(x.scan"")*" ":f[x]}}

Maybe there is a better way, but:

  • x*0 == 0 for integers
  • x*0 == "" for strings
  • x*0 == [] for arrays
share|improve this answer
    
Clever! Thanks for giving me a way to determine types in Python as well! – TidB 1 hour ago

Mathematica, 51 bytes

I've currently got two solutions at this byte count:

#/._?NumberQ->0/.x_String:>StringReplace[x,_->" "]&
StringReplace[#,_->" "]~Check~#&//@#/._?NumberQ->0&

The second one throws a bunch of warnings which can be ignored.

Explanation

In either case, we start by turning numbers into zeros with

#/._?NumberQ->0

Then to process the string, there are two options. Either, we use another substitution that only applies to strings:

.../.x_String:>StringReplace[x,_->" "]

Or, we use the MapAll operator //@ which maps a function over every single element in a nested list. The catch here is that we'll be trying to use StringReplace on zeros as well as the symbol List (since //@ also goes through the heads of expressions), so we need to use Check (sort of like a catch statement in other languages) to avoid wreaking havoc with those values:

StringReplace[#,_->" "]~Check~#&//@...
share|improve this answer

Perl 6, 34 bytes

{.deepmap:{$_~~Str??" "x.comb!!0}}

Expanded:

{                            # A lambda
    .deepmap: {              # Deep-clone the lambda arg with leaf nodes transformed as such:
        $_ ~~ Str            # If it's a string,
            ?? " " x .comb   # then use space repeated by the string's length,
            !! 0             # else use the number zero.
    }
}

Recursive version that doesn't use the deepmap built-in, is 51 bytes:

sub f(\a) {a~~Str??" "x a.comb!!a~~List??a».&f!!0}
share|improve this answer

GAP, 91 bytes

GAP has a method Zero that returns the neutral additive element corresponding to an element of an additive structure. That handles numbers and even lists of numbers which are considered vectors, but not arbitrary lists. So let's add these and Chars and use that Strings are lists of Chars:

InstallOtherMethod(Zero,[IsChar],c->' ');
InstallOtherMethod(Zero,[IsList],l->List(l,Zero));

(I'm not counting the newline as it isn't needed.) Of course this is far away from the intended use of Zero, and GAP would complain if I hadn't used InstallOtherMethod. Now I can do:

gap> Zero([[["H"],"e",1,1,0],[[-3],"arth"]]);
[ [ [ " " ], " ", 0, 0, 0 ], [ [ 0 ], "    " ] ]

I wouldn't say that the builtin does most of the job, one might rather suspect that writing a normal function should be shorter, but my best try doing that was 92 bytes long:

f:=function(x)if IsInt(x)then return 0;elif IsList(x)then return List(x,f);fi;return' ';end;
share|improve this answer

Groovy, 53 bytes

{[it].collectNested{it in String?" "*it.size():0}[0]}

This is an unnamed closure. Try it here!

Explanation:

Groovy has this method .collectNested which helps to iterate through a list as if it was flattened.

To handle special cases where only an integer or a string is passed without a list, simply wrap every input into a list and output the first element.

share|improve this answer

Haskell, 115 bytes

My language cannot handle any mix of numbers and strings in lists (but of course you can define a sum type and put that in a list), and its standard lists cannot handle differently nested lists. So I'm just doing what it can handle. I think that is not unfair because it is still long, and I mainly do it to show features of haskell that are rarely seen in haskell golfing solutions. Note that Strings are lists of Chars.

class N a where n::a->a
instance N Double where n _=0
instance N Char where n _=' '
instance N a=>N[a]where n=map n

This handles any number as Double:

*Main> n 42
0.0
*Main> n 123.456
0.0
*Main> n "hi"
"  "
*Main> n [[1,2],[3,4,5]]
[[0.0,0.0],[0.0,0.0,0.0]]
*Main> n ["hello","world!"]
["     ","      "]
share|improve this answer
    
It should be shorter to define a data structure with data N=S[Char]|I Int|L[N] and a recursive function on that. – Zgarb 3 hours ago
    
You're probably right I guess, but that's less interesting and still looks like not really solving the problem (I admit it actually is closer). I'll leave that for someone else. – Christian Sievers 3 hours ago
    
integers? How about test case 3.? – Adám 3 hours ago
    
@Adám Oh you're right, and unfortunately I can't claim my language doesn't have those. Can I only handle Doubles? I can input them without decimal point. – Christian Sievers 2 hours ago
    
@ChristianSievers Yes, that's fine. Basically, you should be able to handle whatever an import (if possible) from the given JSON would give you. – Adám 2 hours ago

PHP, 91 bytes

function f($a){return!is_array($a)?is_string($a)?str_pad("",strlen($a)):0:array_map(f,$a);}

if parameter is array: recurse using array_map.
else if parameter is string: generate a strings of spaces with the same length.
else 0.

is_string saves one byte over is_numeric; negating is_array() renders parentheses obsolete. Altogether it´s 17 bytes shorter than if()recursion-loop;else x?string:number with a call by reference.

share|improve this answer

Python 2, 54 bytes

g=lambda d:0if d*0==0else " "*len(d)if d*0==""else map(g,d)

uses G B's way to determine types

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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