Convert ASCII box drawing into Unicode

16

4

I am shamelessly posting a request for something I would actually find useful. The task is to take an arbitrary ascii box drawing like this

     |
+----+----+
| state A +---+
+---------+   |
              |
         +----v----+
         | state B |
         +---------+

... and turn it into something more beautiful using unicode box drawing characters, e.g.

     │
╭────┴────╮
│ state A ├───╮
╰─────────╯   │
              │
         ╭────v────╮
         │ state B │
         ╰─────────╯

In more detail:

  • convert only + - | characters - other characters should be unchanged
  • use

    • BOX DRAWINGS LIGHT VERTICAL (U+2502) │
    • BOX DRAWINGS LIGHT HORIZONTAL (U+2500) ─
    • BOX DRAWINGS LIGHT ARC DOWN AND RIGHT (U+256D) ╭
    • BOX DRAWINGS LIGHT ARC DOWN AND LEFT (U+256E) ╮
    • BOX DRAWINGS LIGHT ARC UP AND LEFT (U+256F) ╯
    • BOX DRAWINGS LIGHT ARC UP AND RIGHT (U+2570) ╰
    • BOX DRAWINGS LIGHT VERTICAL AND LEFT (U+2524) ┤
    • BOX DRAWINGS LIGHT VERTICAL AND RIGHT (U+251C) ├
    • BOX DRAWINGS LIGHT DOWN AND HORIZONTAL (U+252C) ┬
    • BOX DRAWINGS LIGHT UP AND HORIZONTAL (U+2534) ┴
    • BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL (U+253C) ┼

    • - always replaced with U+2500

    • | always replaced with U+2502
    • + is replaced with a unicode character that depends on the 4 characters north, south, east and west of it (if they exist)
    • < and > are treated as vertical wall segments if north or south of a + (so that you can have arrows terminating in vertical walls of a box)
    • v and ^ are treated as horizontal wall segments if east or west of a + (so that you can have arrows terminating in horizontal walls of a box)
    • + is treated as a wall segment if either north, south, east or west of a + (so that lines can connect next to a box corner)

Testcases

+-+     +---+   +---+   |
| +--   |ABC|  -+   |  +++
+-+     ++--+   +---+  +-+
         |
         +--->
  |           +--+
+-v+   +---+  |  |  +-----+
|Hi|  ->   |  +^-+  |world<-----+
+--+   +---+   |    +-----+     |
               |                +--
   |
---+---
   |

Becomes

╭─╮     ╭───╮   ╭───╮   │
│ ├──   │ABC│  ─┤   │  ╭┴╮
╰─╯     ╰┬──╯   ╰───╯  ╰─╯
         │
         ╰───>
  │           ╭──╮
╭─v╮   ╭───╮  │  │  ╭─────╮
│Hi│  ─>   │  ╰^─╯  │world<─────╮
╰──╯   ╰───╯   │    ╰─────╯     │
               │                ╰──
   │
───┼───
   │

Shortest code wins!

Alex Zeffertt

Posted 2016-05-25T10:46:57.307

Reputation: 291

1Where is the "intersection", i.e. if the + has lines around it everywhere? – Leaky Nun – 2016-05-25T10:48:04.713

1You probably mean Unicode rather than UTF-8 – Luis Mendo – 2016-05-25T11:01:57.037

1Could we have some test cases? Particularly for edge cases like where two boxes touch at an edge or corner (or clarification that this will never happen). – trichoplax – 2016-05-25T11:10:17.210

@LeakyNun I don't think the intersection should ever be needed. Box walls always terminate lines (which will end in one of +,<,>,^,v if they hit a box wall, otherwise they end in |,-). Lines don't enter boxes. Lines don't cross. – Alex Zeffertt – 2016-05-25T11:33:53.247

2Would be nice to post the required outputs for those test cases. – manatwork – 2016-05-25T11:41:56.793

Will boxes ever touch at an edge, e.g. could there ever be pluses in a 'T' shape all touching? Also, there are no test cases that have boxes with a height > 3 or with any other arrow directions. – mbomb007 – 2016-05-25T15:55:11.127

Can the output have additional spaces at the end of each line? – Loovjo – 2016-05-25T19:26:26.900

2Ugh, I was just composing an answer :-( – Neil – 2016-05-25T20:44:14.763

Thanks for all the comments everyone. This is my first golfing expedition so I'm just getting used to the rules! PS: I do now have a code of my own for this which I can post as a reference design if that is a proper thing to do. – Alex Zeffertt – 2016-05-25T22:28:54.067

@Loovjo No, sorry. – Alex Zeffertt – 2016-05-26T13:24:37.540

Answers

2

JavaScript (ES6), 236 bytes

s=>`
${s}
`.split`
`.map((l,i,a)=>l.replace(/[+-|]/g,(c,j)=>c>`-`?`│`:c>`+`?`─`:`┼┬├╭┤╮??┴?╰?╯`[g(a[i-1][j])+g(l[j-1],1)*2+g(l[j+1],1)*4+g(a[i+1][j])*8]),g=(c,f)=>(f?`+-^v`:`+<>|`).indexOf(c)<0).slice(1,-1).join`
`

Neil

Posted 2016-05-25T10:46:57.307

Reputation: 95 035