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

You must accept any single number, character, or string, or possibly recursive array* 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]," "]]

* If your language has several types which can equally well represent arrays like the above examples, you may chose to support only one. Two entries can both win, even though they are using the same language, by each going with a different data type.

share|improve this question
    
What if our language doesn't distinguish between characters and length-1 strings? – xnor yesterday
    
@xnor AFAICT the effect would be the same. – Adám yesterday
    
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 yesterday
    
@xnor Correct. Feel free to edit the question to better reflect this. – Adám yesterday
    
Let us continue this discussion in chat. – Adám yesterday

14 Answers 14

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 yesterday

Python 2, 52 bytes

f=lambda x:1-(x<{})and map(f,x)if x<''else' '*len(x)

Try it online!

How it works

Python lets you compare different types. Numeric types are always smaller than iterables, and iterables are sorted by their type names, so

0 < {} < [] < '' < ()

This way, f does the following.

  • If x is numeric x<{} returns True and 1-(x<{}) returns 0. The code after and does not get executed.

  • If x is iterable, 1-(x<{}) returns 1 (truthy), so the code after and gets executed.

    • If x is a list, x<'' is true and f gets mapped over its items.

    • If x is a string, x<'' is false and x is replaced with a string of spaces of the same length.

share|improve this answer

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 48 bytes

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

{$_~~List??$_».&?BLOCK!!$_~~Str??" "x .comb!!0}

Expanded:

{                          # block-based lambda
    $_ ~~ List             # if argument is a list/array
        ?? $_».&?BLOCK     # then recurse for each element (&?BLOCK is a compile-time var)
        !! $_ ~~ Str       # else if argument is a string
            ?? " "x .comb  # then use space repeated by the string's length,
            !! 0           # else use the number 0
}
share|improve this answer
    
The .deepmap doesn't work correctly for singular inputs like "X" or 7, because it always returns a List. – Brad Gilbert b2gills yesterday
    
Darn, I must have overlooked that (or the task was clarified later). This makes it quite a bit longer. – smls 12 hours ago

Jelly, 4 bytes

nOa⁶

This is a monadic link. Jelly's implicit printing does a lot of splatting; to verify that the output is what it should be, you can view the internal representation with ŒṘ. Note that this exposes strings as lists of characters, which is how the Jelly interpreter implements them.

Try it online!

How it works

nOa⁶  Monadic link. Argument: z

 O    Ordinal; replace all characters with the code points.
      This does not affect numbers.
n     Vectorizing not-equal; compare z with the result to the right, replacing
      characters with 1 and numbers with 0.
  a⁶  Logical AND space; replace all 1's with spaces.
share|improve this answer
    
I was waiting for an APL to come up. Now chose a different one for a 1-byte solution! – Adám yesterday
    
Thanks for the heads up, but I'm not sure I even know how to represent [[["H"],"e",1,1,0],[[-3],"arth"]] in APL... – Dennis yesterday
    
JSON2APLexpr←⎕SE.Dyalog.Utils.repObj 7159⌶ ⋄ JSON2APLexpr'[[["H"],"e",1,1,0],[[-3],"arth"]]' gives ((,⊂,'H') (,'e') 1 1 0) ((,¯3) 'arth'). FYI, 7159⌶ will be ⎕JSON in version 16.0. – Adám yesterday
    
APL can tackle any JSON. However, plenty of APL data cannot be unambiguously represented in JSON. – Adám yesterday
    
That's helpful, thanks. – Dennis 16 hours ago

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

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 yesterday
    
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 yesterday
    
integers? How about test case 3.? – Adám yesterday
    
@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 yesterday
    
@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 yesterday

Python 2, 59 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

 Common Lisp, 87

(defun c(e)(typecase e(list(mapcar'c e))(number 0)(string(map'string(lambda(u)#\ )e))))

Ungolfed

(defun c(e)
  (typecase e
    (list (mapcar #'c e))
    (number 0)
    (string (map 'string (lambda(u) #\space) e))))

Example

> (c '((("H") "e" 1 1 0) ((-3) "arth")))
(((" ") " " 0 0 0) ((0) "    "))
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

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

Pyke, 8 bytes (Old version)

.FZ*0+d&

Explanation:

.FZ*0+d& - for i in deep_for(input):
  Z*     -    i*0
    0+   -   ^ + 0
      d& -  ^ and " "

This no longer works as an update made it so falsies of other types where there are truthies automatically convert to the falsey of the truthy type.

share|improve this answer
    
That's of course acceptable. – Adám yesterday

C#, 197 195 Bytes

a=>{if(a is string||a is char)return new string(' ',(a as string)?.Length??1);try{System.Convert.ToDecimal(a);return 0;}catch{}var b=(object[])a;for(int i=0;i<b.Length;)b[i]=n(b[i++]);return b;};

This function handles char, string, any builtin number type and recursive arrays.

Full program, ungolfed whit output helper:

using System.Linq;    
class Class
{
    public static void Main()
    {
        System.Func<object, object> n = null;
        n = a => 
        {
            if (a is string || a is char)
                return new string(' ', (a as string)?.Length ?? 1);
            try
            {
                System.Convert.ToDecimal(a);
                return 0;
            }
            catch { }

            var b = (object[])a;
            for (int i = 0; i < b.Length;)
                b[i] = n(b[i++]);
            return b;
        };

        var result = n(new object[] { new object[] { new object[] { "H" }, 'e', 1.5, 1, 0 }, new object[] { new object[] { -3 }, "arth" } });
        System.Console.WriteLine(Output(result));
        System.Console.Read();
    }

    static string Output(object x)
    {
        var arr = x as object[];
        if (arr != null)
            return "[" + string.Join(",", arr.Select(Output)) + "]";
        else
            return x.ToString();
    }
};

The using statement is only needed for the output helper, not for the actual function.

Try Online

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.