Written by

Senior Cloud Architect at InterSystems
Discussion Eduard Lebedyuk 路 Aug 5, 2024

Code Golf: Print every character your program doesn't have

Today we have an unusual code golf: build a program (using only printable ASCII characters, tabs and newlines) that prints out exactly the characters in the printable ASCII space (characters 32 to 126) that don't appear in your program's source code (in any order, however many times you want).

As usual, the goal is to produce the shortest code to do this.

My (admittedly not very good, but does the job!) entry:

Classascii.ascii {

ClassMethodascii()
{
    setx="!#$%&'()*+,-./0123456789:;<>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdfghijklmnopqruvwyz{|}~"
}

}

Let's say the characters in the signature:

ClassMethodascii(){}

do not count for program's source code.

Comments

Enrico Parisi 路 Aug 6, 2024

42 characters, but I don't like that code in a class....it's like cheating

43 characters, without feeling cheating 馃槀

0
Eduard Lebedyuk  Aug 6, 2024 to Enrico Parisi

it's like cheating

Reflective programming is not cheating!

0
Robert Barbiaux 路 Aug 7, 2024

Alas, I'm well behind : 54 characters (according to %Dictionary.MethodDefinition Implementation.Size).
Please, enlighten me 馃槄

ClassMethodascii() [ CodeMode = objectgenerator ]
{
 f i=0,83,0,33,29,2,3:1:94,2d%code.Write($c(i+32))
}
0
Eduard Lebedyuk  Aug 7, 2024 to Robert Barbiaux

Well, in that case you might as well do this (down to 41):

ClassMethodascii() [ CodeMode = objectgenerator ]
{
 f i=0,27,0:1:94d%code.Write($c(i+32))
}
0
Robert Barbiaux  Aug 7, 2024 to Eduard Lebedyuk

ah, yes, thanks, comments are indeed part of the source code 馃榿

0
Vitaliy Serdtsev  Aug 9, 2024 to Eduard Lebedyuk

Judging by this code, I probably did not fully understand the conditions of the task. So:

  1. the source code of the method = "聽f聽i=0,27,0:1:94聽d聽%code.Write($c(i+32)) ", size = 42
  2. the following characters are not found in the source code of the method:
    !"#&'*-/568;<>?@ABCDEFGHIJKLMNOPQRSTUVXYZ[\]^_`abghjklmnpqsuvwxyz{|}~
  3. the method should print the characters from point 2
  4. I did not find it in the task conditions [CodeMode = objectgenerator]
Where did I go wrong?
0
Eduard Lebedyuk  Aug 9, 2024 to Vitaliy Serdtsev

I agree that

[ CodeMode = objectgenerator ]

is certainly outside of this code golf conditions (method signature should not be changed), but it's still a creative example.

0
Julius Kavay  Aug 9, 2024 to Eduard Lebedyuk

The problem is, the specification for this task is simple unprecise, and according to my opinion, gives a faulty example. Your exmple code has just a Set command but the task talks about "print out" - hence, I expected to see either a Write "whatever" or at last a Quit "whatever" comand.
Also, if we talk about a method signature, I take in account the number of arguments (maybe their types) only and the return type but never their method keywords, as in the solution from Eduard, hence his solution is not only creative but valid too.
I think, a fair way to mesure the size of a solution is, if you take the size of the routine which will be executed, and that is the INT routine, which is directly (we neglect the possible compiler optimizations, that's the compilers and not the users credit) compiled into a executable. How I got that code (some generator or via a macro or whatever other method) is actually irrelevant.
A very good example for using or not using a method keyword is the "codemode=expression":

/// you save that "Quit " but have to write "codemode=expression"/// which is not taken in account by the Implementation.SizeClassMethod Test() [ codemode = expression]
{
 123
}

/// you have to write "Quit " and save the writing of "codemode..."/// The Implementation.Size counts that "quit "ClassMethod Test2()
{
 quit123
}

Whatever you choose, the corresponding INT code is always "quit ..."

So the bottom line is, either you should define all constraints and conditions or accept each end every clever solution.

0
Timothy Leavitt  Aug 7, 2024 to Timothy Leavitt

(but the solution is dependent on compilation flags - not sure if that invalidates it)

0
Eduard Lebedyuk  Aug 7, 2024 to Timothy Leavitt

I am very interested how compilation flags help you with this.

0
Julius Kavay  Aug 9, 2024 to Timothy Leavitt

It shouldn't be invalid because there are no corresponding constraints.

At the beginning, I thought not to participate, because of the problematic specification and example, but now, as I see, I'm not the only one with questions without answers, hence I offer an 38 char solution too (including the hint to compiler flags) and a shorter version with 34 chars, a correkt result but with "a little bit" of side effect.

0
Timothy Leavitt  Aug 13, 2024 to Julius Kavay

This is old enough to post a spoiler now - I got down to 35 with the *i trick; what's the 34-character solution?
 

 

Spoiler

 
Classascii.ascii
{

ClassMethodascii()
{
 f i=32:1:126{w:$t(+6)'[$c(i) *i}
}

}

 

0
Julius Kavay  Aug 13, 2024 to Timothy Leavitt

We need the source code, so the compiler flag for keeping the source must be on. The 38 char version does the job

ClassMethodascii() [ ProcedureBlock = 0 ]
{
x	n i f i=32:1:126w:$t(x)'[$c(i) *i
}

The 34-character version does the job too  has a side effect (leaving the variable i with the last value)

ClassMethodascii() [ ProcedureBlock = 0 ]
{
y	f i=32:1:126w:$t(y)'[$c(i) *i
}
0
Enrico Parisi 路 Aug 7, 2024

OK, it seems that I did not understood the challenge! 馃槀

BUT, the instructions read as:

"...build a program (using only printable ASCII characters, tabs and newlines) that prints out...."

What's your concept of "prints out"?

I understand that the provided sample solution doe not printout anything, but the instructions also says:

"....exactly the characters in the printable ASCII space (characters 32 to 126) that don't appear in your program's source code..."

Again, my concept of source code include...well, all the code, including string constants in the source code, so the provided sample solution does not satisfy the conditions because it contains ALL the printable ASCII space!
Maybe it correct because sing it contains all the  printable ASCII space, it does not prints out anything?!

0
Robert Barbiaux  Aug 7, 2024 to Enrico Parisi

Yes Enrico, it is my understanding exactly : if your program code (i.e. the lines in the routine generated by the compiler) contains all printable ASCII characters, it should output an empty string. Of course it sounds silly to devise a very clever way to output an empty string, but after all, golf - from a practical point of view - is a silly sport isn't it ? 馃ぃ

0
Eduard Lebedyuk  Aug 7, 2024 to Enrico Parisi

There are to valid ways to solve this code golf:

  • Create a program that contains all ASCII characters in the source code (so it does not have to print anything)
  • Create a program which prints ASCII characters not present in a source code

Both approaches are valid, sample solution uses approach 1.

"Print out" is any output the program produces so if you for example add 1/0 at the end it might save you a few characters.

0
Robert Barbiaux  Aug 7, 2024 to Eduard Lebedyuk

 Using the second approach  : edited down to 39 characters 

ClassMethodascii()
{
 f i=32:1:126w:$t(ascii+1)'[$c(i) *i
}
0
Vitaliy Serdtsev  Aug 9, 2024 to Robert Barbiaux

I would like to draw your attention to a number of points:

  • this code will work correctly only when the compilation flag "k" is enabled, otherwise $TEXT will not return anything.
    k - Keep source. When this flag is set, source code of generated routines will be kept.
  • this code will not work correctly in Cach茅, because there the label name will be "zascii", non "ascii"
  • if you look at the generated INT code, you can see the "}" character at the end, which will return $t(ascii+1), which will lead to an incorrect result
    ascii()聽methodimpl {
    聽f聽i=32:1:126聽w:$t(ascii+1)'[$c(i)聽*i聽}
0
Vitaliy Serdtsev 路 Aug 14, 2024
 

size = 59 (does not depend on the "k" flag)

ClassMethod ascii()
{
 i=32:1:126 w:^oddDEF($this,"m","ascii",30,1)'[$c(i) *i
}
 

size = 76 (+without the "for" loop)

ClassMethod ascii()
{
 w $tr(##class(%Net.SMTP).#PrintableAscii,^oddDEF($this,"m","ascii",30,1))
}
0