An isolated character is a character (other than a newline) that doesn't have an adjacent character of the same type. Adjacent characters can be to the left, the right above or below, but not diagonals. For example in the following text H is isolated:


All the other characters are not isolated because each of them has at least one other character of the same type adjacent.

Your task is to write a program that takes a string as input and determines the number of isolated characters.


You answer will be scored by two metrics. The first is the number of isolated characters in your program. You should aim to minimize this. The second will be the number of bytes in your program. You should minimize this as well. Program size will act as a tie breaker for the first criterion.

Additional Rules

  • You should support input on the printable ascii range plus any characters you use in your program.

  • You may consider a line break to either be a newline character or a newline followed by a line feed.

  • You may take input in any reasonable format. This includes a list of lines.

Test Cases









  • 2
    \$\begingroup\$ Is an empty string valid input and if so would it score 0? Also how flexible is input type? List of lines fine? \$\endgroup\$
    – Veskah
    Commented Sep 13, 2018 at 21:53
  • 1
    \$\begingroup\$ @DimChtz Because it has a Y below it. \$\endgroup\$ Commented Sep 13, 2018 at 21:58
  • 2
    \$\begingroup\$ The first metric can be circumvented in any programming language and every answer has a 0 score now. \$\endgroup\$
    – G B
    Commented Sep 14, 2018 at 10:22
  • 1
    \$\begingroup\$ @GB Indeed. I guess it's not too late for turning it into a restricted-source challenge instead and disallow isolated characters altogether. \$\endgroup\$
    – Arnauld
    Commented Sep 14, 2018 at 10:56
  • 1
    \$\begingroup\$ An interesting variation on this puzzle might be to make it a "toroidal" board (top wraps to bottom and left wraps to right). \$\endgroup\$
    – Wossname
    Commented Sep 14, 2018 at 12:57

9 Answers 9


Python 2, 0 (350 344 314 309 301 298 291 bytes)

def f(tt):11
def f(tt):
 r =0#.split('\n')
#r  0#
 for  ii,ll in enumerate(tt):
  for jj,cc in enumerate(ll):
    r+=1-(cc in ll[(jj or 2)-1:jj+2:2]    +''.join(ll[jj:
 jj+1]for ll in tt[(ii or 2)-1:ii+2:2]))##+''.join(ll[jj:
#  +1]for 
#print r
 print r

Try it online!

-7 bytes, thanks to Jo King

  • \$\begingroup\$ 291 bytes \$\endgroup\$
    – Jo King
    Commented Sep 14, 2018 at 11:54

Clean, 0 (439 ... 415 bytes)

-11 thanks to Ørjan Johansen

Finally a challenge where I can score 0 with Clean!
(and normally it's bad at source-layout challenges!)

  module d
import StdEnv,ArgEnv,Data.List,Data.Maybe
import StdEnv,ArgEnv,Data.List,Data.Maybe
Start=sum[1\\i<-l&v<-[0..],_<-i&u<-[0..]|all((<>)(?u v))[?(u-1)v,?(u+1)v,?u(v-1),?u(v+1)]]
Start=sum[1\\i<-l&v<-[0..],_<-i&u<-[0..]|all((<>)(?u v))[?(u-1)v,?(u+1)v,?u(v-1),?u(v+1)]] 

Try it online!

The TIO link uses module main due to the way Clean is implemented on TIO, but module d will work if you name the file d.icl instead of main.icl as TIO does.

One of the old lines explained (new version is the same thing in a different order):

Start                                       // entry point
 = let                                      // define locals
  l = mklines                               // `l` is argument split at newlines
   [c \\ c <-: getCommandLine.[1]];         // the second command-line arg turned into a [Char]
  ? x y                                     // function ? of coordinate (x,y)
   = mapMaybe                               // if the argument isn't Nothing
    (\k = k!?x)                             // try taking the `x`-th index
    (l!?y)                                  // of the `y`-th index of `l`
  in                                        // in the context of
   sum [                                    // the sum of
    1                                       // the integer one
    \\ i <- l & v <- [0..]                  // for every index in `l`
    , _ <- i & u <- [0..]                   // for every subindex in `l`
    | all (                                 // where all of the second argument
      (<>)(?u v)                            // doesn't equal the first argument
     ) [?(u-1)v, ?(u+1)v, ?u(v-1), ?u(v+1)] // over every adjacent element
  • 1
    \$\begingroup\$ Not using let saves 11 bytes. \$\endgroup\$ Commented Sep 14, 2018 at 5:35
  • \$\begingroup\$ @ØrjanJohansen Thanks! I also changed the module header since we have an adjacent d handy \$\endgroup\$
    – Οurous
    Commented Sep 14, 2018 at 5:37

JavaScript (ES6), 0 (154 bytes)

Saved 2 4 bytes thanks to @ØrjanJohansen

Takes input as an array of strings.

s  =>
.map((c,x  )=>[...s]

Try it online!

  • \$\begingroup\$ 156 bytes \$\endgroup\$ Commented Sep 15, 2018 at 6:35
  • \$\begingroup\$ 153 \$\endgroup\$
    – l4m2
    Commented Feb 6, 2022 at 2:54
  • \$\begingroup\$ 147 \$\endgroup\$
    – l4m2
    Commented Feb 6, 2022 at 2:58

Jelly, 0 (41 27 25 bytes)


Try it online!

Takes input as list of lines. The first line in the code never does anything and is only there to minimize isolated characters.

Ỵ                 Split the text on newlines.
 ŒĠ               Group the multidimensional indices by their value.
      €           For each list of indices:
   ạ                Take the absolute difference...
    þ`              ...between each pair.
       Ẏ          Concatenate the lists of differences.
        §         Sum the x & y differences. This computes the Manhattan distance.
                  At this point we have a list for each character in the text of 
                  Manhattan distances between it and it's identical characters. 
         1eⱮ      Is there a 1 in each of the lists? None for isolated characters.
            C     Complement: 0 <-> 1.
             S    Sum. Counts the isolated characters

MATL, 0 (54 bytes)


Input is a cell array of strings, one for each line: {'line 1', 'line 2', 'and line 3'}.

Try it online! Or verify test cases and source code.


05AB1E, 0 (101 bytes)


Try it online.

This is one of the ugliest and longest 05AB1E programs I've ever written.. >.> This challenge is deceivingly hard in 05AB1E. I have no doubt in mind the byte-count can at least be halved or even three/four times as small by using a different approach (or even with a similar approach), but I currently don't see how. I'm just glad it's working right now.. If someone else posts a much shorter 05AB1E answer with some smart tricks I'll probably delete this answer out of shame... xD


žGç                # Character with unicode 32768 ('耀')
   U               # Pop and store it in variable `X`
                   # (This character is not part of the printable ASCII, nor of my 05AB1E code)
|                  # Take the multi-line input as list
                   #  i.e. "Ybb\nYH%\n%%%%" → ["Ybb","YH%","%%%%"]
 €S                # Convert each string to a list of characters
                   #  i.e. ["Ybb","YH%","%%%%"] → [["Y","b","b"],["Y","H","%"],["%","%","%","%"]]
   Xζζ             # Zip with character `X` as filler twice to make the lines of equal length
                   #  i.e. [["Y","b","b"],["Y","H","%"],["%","%","%","%"]]
                   #   → [["Y","b","b","耀"],["Y","H","%","耀"],["%","%","%","%"]]
      D            # Duplicate this list
"             "    # Create a string
               ©   # Which we store in the register (without popping)
                .V # And execute that string as 05AB1E code
 ε                 #  Map each inner list to:
  γ                #   Split in chunks of the same characters
                   #    i.e. [["Y","b","b"],["Y","H","%"],["%","%","%","%"]]
                   #     → [[["Y"],["b","b"]],[["Y"],["H"],["%"]],[["%","%","%","%"]]]
   ε               #   Map each of those to:
    D              #    Duplicate the current inner list
     gDi           #    If its length is exactly 1:
        s          #     Swap so the mapping keeps the duplicated single character (as list)
       ë           #    Else:
        Xи         #     Take character `X` repeated the length amount of times
                   #      i.e. ["%","%","%","%"] (length 4) → ["耀","耀","耀","耀"]
          ]        #  Close the if-else and both maps
           ˜       #  Flatten the list to a single list of characters
                   #   i.e. [[["Y"],["耀","耀"],["耀"]],[["Y"],["H"],["%"],["耀"]],[["耀","耀","耀","耀"]]]
                   #    → ["Y","耀","耀","耀","Y","H","%","耀","耀","耀","耀","耀"]
s                  # Swap so the duplicate list is at the top of the stack
 ø                 # Swap its rows and columns
                   #  i.e. [["Y","b","b","耀"],["Y","H","%","耀"],["%","%","%","%"]]
                   #   → [["Y","Y","%"],["b","H","%"],["b","%","%"],["耀","耀","%"]]
  ®.V              # Execute the same piece of code again that we've stored in the register
     €S            # Convert each to a list of characters
                   #  i.e. [[["耀","耀"],["%"]],[["b"],["H"],["%"]],[["b"],["耀","耀"]],[["耀","耀"],["%"]]]
                   #   → [["耀","耀","%"],["b","H","%"],["b","耀","耀"],["耀","耀","%"]]
       ø           # Swap its rows and columns back again
                   #  i.e. [["耀","b","b","耀"],["耀","H","耀","耀"],["%","%","耀","%"]]
        ˜          # Flatten this list as well
‚                  # Pair both lists together
                   #  i.e. [["Y","耀","耀","耀","Y","H","%","耀","耀","耀","耀","耀"],
                   #        ["耀","b","b","耀","耀","H","耀","耀","%","%","耀","%"]]
 ø                 # Swap its rows and columns to create pairs
                   #  i.e. [["Y","耀"],["耀","b"],["耀","b"],["耀","耀"],["Y","耀"],["H","H"],["%","耀"],["耀","耀"],["耀","%"],["耀","%"],["耀","耀"],["耀","%"]]
  ʒË}              # Filter out any inner lists where both characters are not equal
                   #  i.e. [["耀","耀"],["H","H"],["耀","耀"],["耀","耀"]]
     ʒXå≠}         # Filter out any inner lists that contain the character `X`
                   #  i.e. [["H","H"]]
g                  # Take the length as result
                   #  i.e. [["H","H"]] → 1
 q                 # Stop the program, making all other characters no-ops
                   # (and output the length above implicitly)

Python 3, 0 (323 bytes)

def f(s,e=enumerate):S={(x,y,c)for y,l in e(s.split("\n"))for x,c in e(l)};return-sum(~-any((x+u,y+v,c)in S for u,v in[(1,0),(~0,0),(0,~0),(0,1)])for x,y,c in S)
def f(s,e=enumerate):S={(x,y,c)for y,l in e(s.split("\n"))for x,c in e(l)};return-sum(~-any((x+u,y+v,c)in S for u,v in[(1,0),(~0,0),(0,~0),(0,1)])for x,y,c in S)

Try it online!


Ruby, score 0, 237 209 bytes


Try it online!


JavaScript (Node.js), 0 (279 bytes)


Try it online!

Receive input as array of lines.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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