Howdy! I'm the sheriff of code golf!

30

3

It's likely that anyone who used Twitter a couple of months ago would know about the 'Howdy! I'm the sheriff of X" meme. Where a simple image of a sheriff is drawn with emoji, and changes to fit a theme. So I thought it was time for the Sheriff of Code Golf. Here he is:

    ###
   #####
    ###
    ###
    ###
     #
   #####
  #  #  #
 #   #   #
 #   #   #
     #
    ###
   #   #
   #   #
   #   #
   #   #

This one in particular has 'pixels' which are one character wide, and one character high. To generate him, the arguments will be 1 and 1.

What if he is to be wider than he is tall?

      ######
    ##########
      ######
      ######
      ######
        ##
    ##########  
  ##    ##    ##
##      ##      ##
##      ##      ##
        ##
      ######
    ##      ##
    ##      ##
    ##      ##
    ##      ##

He's got a height of 1, but a width of 2.


Rules:

  • The challenge is to write code to draw your own Sheriff of Code Golf, in the fewest characters possible.
  • Use any programming language your heart desires.
  • Your code should take two arguments, both of which are integers, for the height and width of the Sheriff.
  • The output should be composed of single white spaces for the background, and any other character(s) you choose for the Sheriff. (I've used hashes for the test cases, but it doesn't matter what you use).
  • It should be possible for the height to be a negative integer, inverting the image.
  • The width can be a negative integer, but because the image is symmetrical, it will be identical to it's positive value.
  • Trailing white-spaces are irrelevant.
  • If either argument is 0, that dimension is 'flattened' to a single row or column. The length of this line is the other argument multiplied by the height, or width of the Sheriff, respectively.
  • If both arguments are 0, both lines are 'flattened', leaving a single positive character.
  • Not essential, but please include a link to an online interpreter such as tio.run
  • The output should be a string, over multiple lines, or output to the console.

Test Cases

1 high, 1 wide

    ###
   #####
    ###
    ###
    ###
     #
   #####
  #  #  #
 #   #   #
 #   #   #
     #
    ###
   #   #
   #   #
   #   #
   #   #   

2 high, 1 wide

    ###
    ###
   #####
   #####
    ###
    ###
    ###
    ###
    ###
    ###
     #
     #
   #####
   #####
  #  #  #
  #  #  #
 #   #   #
 #   #   #
 #   #   #
 #   #   #
     #
     #
    ###
    ###
   #   #
   #   #
   #   #
   #   #   
   #   #
   #   #
   #   #
   #   #  

1 high, 2 wide

      ######
    ##########
      ######
      ######
      ######
        ##
    ##########  
  ##    ##    ##
##      ##      ##
##      ##      ##
        ##
      ######
    ##      ##
    ##      ##
    ##      ##
    ##      ##

2 high, 2 wide

      ######
      ######
    ##########
    ##########
      ######
      ######
      ######
      ######
      ######
      ######
        ##
        ##
    ##########  
    ##########  
  ##    ##    ##
  ##    ##    ##
##      ##      ##
##      ##      ##
##      ##      ##
##      ##      ##
        ##
        ##
      ######
      ######
    ##      ##
    ##      ##
    ##      ##
    ##      ##
    ##      ##
    ##      ##
    ##      ##
    ##      ##

-1 high, 1 wide

   #   #
   #   #
   #   #
   #   #   
    ###
     #
 #   #   #
 #   #   #
  #  #  #
   #####
     #
    ###
    ###
    ###
   #####
    ###

1 high, -1 wide

    ###
   #####
    ###
    ###
    ###
     #
   #####
  #  #  #
 #   #   #
 #   #   #
     #
    ###
   #   #
   #   #
   #   #
   #   #   

0 high, 0 wide

#

1 high, 0 wide

#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#

0 high, 2 wide

##################

Have fun, y'all!

AJFaraday

Posted 2018-07-26T09:33:01.667

Reputation: 10 466

1

This challenge has reminded me of the Inverted World novel.

– Charlie – 2018-07-26T09:46:07.850

Related: Picture of an old friend in ASCII art (variable scales; no inversion or flattening)

– Luis Mendo – 2018-07-26T09:58:41.563

Observation: 1 high, 2 wide is the most human looking of the test cases, though I'm obligated to cheer for the Australian in the middle of it – Jo King – 2018-07-26T11:40:40.763

@JoKing If I was naming them, I'd definitle have (-1, 1) as 'Australian' and (-1, 2) as 'Realistic Australian'. Although... Perhaps that could be misunderstood. – AJFaraday – 2018-07-26T11:44:59.957

Closely related – Digital Trauma – 2018-07-26T15:23:48.927

Why do the 1-wide versions have an extra column of spaces at the left? – Οurous – 2018-07-27T00:24:20.263

Answers

39

JavaScript (ES6), 171 bytes

Takes input in currying syntax (width)(height). Returns an array of strings.

w=>h=>[...Array((h>0?h:-h)*16||1)].map((_,y)=>'012345678'.replace(/./g,x=>' #'[((c=+'3733317900134444'[(h<0?16-~y/h:y/h)|0]||17)>>4-x|c>>x-4)&1|!h].repeat(w>0?w:-w))||'#')

Try it online!

How?

Only the left half of the sheriff is encoded as binary bitmasks, including the middle column:

    ##.         00011     3
   ###..        00111     7
    ##.         00011     3
    ##.         00011     3
    ##.         00011     3
     #          00001     1
   ###..        00111     7
  #  #  .       01001     9
 #   #   .  --> 10001 --> 17
 #   #   .      10001     17
     #          00001     1
    ##.         00011     3
   #   .        00100     4
   #   .        00100     4
   #   .        00100     4
   #   .        00100     4

Because there are only two values greater than \$9\$ and they're both equal to \$17\$, we can replace them with \$0\$ in order to have one character per row and still have a rather straightforward decoding process. Hence the packed string:

'3733317900134444'

For \$0 \le x \le 8\$ and \$0 \le y \le 15\$, the 'pixel' at \$(x,y)\$ is given by:

' #'[                                  // character lookup:
  (                                    //   0 = space
    (                                  //   1 = '#'
      c = +'3733317900134444'[y] || 17 // extract the bitmask for this row; 0 -> 17
    )   >> 4 - x                       // test the left part, middle column included
    | c >> x - 4                       // test the right part, middle column also included
  ) & 1                                // isolate the least significant bit
]                                      // end of character lookup

Arnauld

Posted 2018-07-26T09:33:01.667

Reputation: 111 334

6No matter how many answers you post, I'm impressed every single time.. – Kevin Cruijssen – 2018-07-27T11:24:09.563

I've shortened your version by 10 bytes. I'm not sure whether to post it as my own or to just enhance yours. Mine draws inspiration from yours so it looks almost as a duplicate. Great thinking by the way :D. Good job! – ibrahim mahrir – 2018-07-29T15:24:09.420

... by 8 bytes not 10. :-P – ibrahim mahrir – 2018-07-29T15:31:29.063

@ibrahimmahrir Sometimes, there's a thin line between outgolfed and improved. So, it's up to you. If you think your implementation is different enough, I don't mind at all if you post it as a separate answer. – Arnauld – 2018-07-29T16:12:41.437

I think it's just an improvment. The idea is to use characters codes as bitmaskes. That will save some space as each character will represent the whole row instead of just half of it. You can get the character code using String#charCodeAt. – ibrahim mahrir – 2018-07-29T16:21:40.360

Here it is in action: TIO. And I've just noticed it is not shortened by 8 bytes but by 5. text-encoding-face-palm. It is however shortened by 8 characters, so.... I still don't know how golfing works, yet.

– ibrahim mahrir – 2018-07-29T16:21:44.980

2@ibrahimmahrir I see. I think I'd better let this one as-is. You can still post yours as a separate alternate version. That's fine with me! (I'd make sure to add a link in my answer.) – Arnauld – 2018-07-29T16:30:13.027

16

Python 2, 228 218 202 189 173 bytes

lambda h,w:sum(([''.join('# '[int(n)]*abs(w)for n in bin([62,120,224,238,438,750][int(l)])[2:])or'#']*abs(h)for l in'1211102455013333'),[])[::1-(h<0)*2]or['#'*9*abs(w)or'#']

Try it online!


Alternatives:

Python 2, 173 bytes

lambda h,w:sum(([''.join('# '[int(n)]*abs(w)for n in bin(ord(' >w(8\x96I'[l])*l)[2:])or'#']*abs(h)for l in map(int,'3433314655132222')),[])[::1-(h<0)*2]or['#'*9*abs(w)or'#']
lambda h,w:sum(([''.join('# '[int(n)]*abs(w)for n in bin(ord(' >w(8\x96I'[int(l)])*int(l))[2:])or'#']*abs(h)for l in'3433314655132222'),[])[::1-(h<0)*2]or['#'*9*abs(w)or'#']

TFeld

Posted 2018-07-26T09:33:01.667

Reputation: 19 246

8

Perl 5, 169 166 157 bytes

@a=map"$_\n",(split 1,'  #####1   ###1    #1 #  #  #1#   #   #1  #   #')
[1011120344215555=~/./g];
print s/./$&x abs"@F"/ger x abs$F[1]for$F[1]<0?reverse@a:@a;

Try it online!

Maybe more could be gained by bit fiddling.

Kjetil S.

Posted 2018-07-26T09:33:01.667

Reputation: 1 049

1

Great approach! I've played with your answer and with a few changes you can save quite a few bytes: Try it online! It's exactly the same approach just using slightly different I/O and a few tricks to reorder elements and store them for fewer bytes! Happy to elaborate on anything if needed!

– Dom Hastings – 2018-07-29T09:31:07.087

Thx for the tip on split, I'm using that now and saved two bytes. Also shaved one off by loosing the 's around the indexes. Couldn't get say to work though. – Kjetil S. – 2018-07-29T13:45:04.227

Thx also for getting width and height "for free" with -a, lost 9 more bytes with that. – Kjetil S. – 2018-07-29T14:02:23.573

No problem at all! You can enable say with -M5.010, but not everyone likes to, you could use -l instead and keep print, but if not, you can use a literal newline or $_.$/ for -1. Nice to see another Perl golfer! – Dom Hastings – 2018-07-29T14:21:00.197

Couldn't leave this alone and managed to reduce by a few more. say wasn't working because the newline was appended in the map so to use it necessitates a slightly different call. I also realised that when your code ends in a variable and you're using -p or something you can use @; as it includes that: Try it online! Hope you don't mind my comments!

– Dom Hastings – 2018-07-29T19:22:05.413

7

Charcoal, 61 bytes

NθNη¿θF⪪”{“↷C¿2t´⁴Q19·“*Ty”!E↔θ∨⭆ι×μ↔η#×#∨×⁵↔η¹‖OO←∨↔η¹¿‹θ⁰‖↓

Try it online! Link is to verbose version of code. Explanation:

NθNη

Input the dimensions.

¿θF⪪”{“↷C¿2t´⁴Q19·“*Ty”!

If the height is nonzero, loop over the the right half of the sheriff...

E↔θ

... repeating the absolute height number of times...

∨⭆ι×μ↔η#

... if the width is nonzero then repeating each character the absolute number of times, otherwise a #.

×#∨×⁵↔η¹

But if the height is zero, then repeat # 5 times the absolute width, but at least 1 #.

‖OO←∨↔η¹

Reflect to produce the left half of the sheriff.

¿‹θ⁰‖↓

If the height is negative, flip the sheriff.

Neil

Posted 2018-07-26T09:33:01.667

Reputation: 95 035

4

Python 2, 217 216 bytes

h,w=input();t=[];w=abs(w)
for i in range(16):c=bin(32+int('37333179HH134444'[i],26))[-5:];t+=[[''.join(abs(w)*' #'[d>'0']for d in c+c[3::-1]),'#'][w==0]]*abs(h)
print['\n'.join(t[::[1,-1][h<0]]),'#'*(w*16or 1)][h==0]

Try it online!

A Pythonic riff on Arnauld's approach.

Ugh! Now works for all edge conditions...

Chas Brown

Posted 2018-07-26T09:33:01.667

Reputation: 8 959

3

Clean, 299 275 272 bytes

import StdEnv,Data.List
f=flatlines
r=repeatn
$0 0=['#']
$h w#w=abs w
|h==0=r(w*9)'#'
|w<1=f(r(abs h*16)['#'])
=f(if(h<0)reverse id[cjustify(w*9)(intercalate(spaces((0xde35945rem n)*10/n*w))(r((0xc8d88154f8fberem n)*10/n)(r w'#')))\\n<-map((^)10o~)[-16..0],_<-[1..abs h]])

Try it online!

Οurous

Posted 2018-07-26T09:33:01.667

Reputation: 7 916

2

Powershell, 174 170 bytes

Inspired by Arnauld's Javascript

param($w,$h)('CGCCCAGIQQACDDDD'[((0..15),(15..0))[$h-lt0]],31)[!$h]|%{$n=+$_
,(-join(4..0+1..4|%{,' #'[($n-shr$_)%2]*[Math]::Abs($w)}),'#')[!$w]*[Math]::Abs(($h,1)[!$h])}

Ungolfed, explained and test scripted:

<#

Script uses 5 bits of integer as 5 left chars of a line of a sheriff
Script ignores other bits in this integer, so we can use 6 bit to take a ASCII letter
    ##.         1 00011     C
   ###..        1 00111     G
    ##.         1 00011     C
    ##.         1 00011     C
    ##.         1 00011     C
     #          1 00001     A
   ###..        1 00111     G
  #  #  .       1 01001     I
 #   #   .  --> 1 10001 --> Q
 #   #   .      1 10001     Q
     #          1 00001     A
    ##.         1 00011     C
   #   .        1 00100     D
   #   .        1 00100     D
   #   .        1 00100     D
   #   .        1 00100     D

#>

$f = {

param($w,$h)
(
    'CGCCCAGIQQACDDDD'[             # 5 bits of each char correspond to 5 left symbols of line of sheriff.
        ((0..15),(15..0))[$h-lt0]], # forward or reverse sequence of chars
    31                              # or sequence of one element = 11111
)[!$h]|%{                           # choose a sequence and for each
    $n=+$_                          # integer or ASCII code
    ,(  -join(
            4..0+1..4|%{            # loop on bit range 4..0 and append fliped range 1..4
                ,' #'[($n-shr$_)%2]*[Math]::Abs($w)
            }                       # returns space or # depend on bit, repeat $w times
        ),
        '#'                         # returns # for $w equal 0
    )[!$w]*[Math]::Abs(($h,1)[!$h]) # choose a sheriff line, repeat $h times
}

}

@(
    ,(1,0)
    ,(0,1)
    ,(1,-1)
    ,(0,0)
    ,(1,1)
    ,(0,0)
    ,(-2,-1)
    ,(0,0)
    ,(2,2)
) | % {
    $w,$h = $_
    $r = &$f $w $h
    $r
}

mazzy

Posted 2018-07-26T09:33:01.667

Reputation: 4 832