Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output or return in Java without using the letter e or digit 5

Tags:

java

escaping

For this challenge on PCG.SE, one is required to write a function/program that returns/outputs the first N primes.

However, the characters with prime code points are not allowed in the program.

Two of these characters are 5 and e. The code points of either letter contain a 5. Because of this, \u{codepoint} won't work for those two letters.

Using escapes, I can remove all prime characters from the code except for the e in return.

I could use System.out or FileDescriptor.out but both contain the letter e.

Is there any way to return or output without using an e or 5?

For reference here is my code with characters escaped:

int[]b(int b\u0029{
    int c,d,f[]\u003d{}\u003b
    for(f\u003dj\u0061v\u0061.util.Arr\u0061ys.copy\u004ff(f,b\u0029\u003bb-->0\u003b\u0029
        for(d\u003d0,c\u003d2\u003bf[b]<1\u003bf[b]\u003dd<1?c:f[b],d\u003d0,c\u002b\u002b\u0029
            for(int h:f\u0029
                d\u003dh>0&&c\u002fh*h\u003d\u003dc?1:d\u003b
    return f;
}

Without characters escaped:

int[]b(int b){
    int c,d,f[]={};
    for(f=java.util.Arrays.copyOf(f,b);b-->0;)
        for(d=0,c=2;f[b]<1;f[b]=d<1?c:f[b],d=0,c++)
            for(int h:f)
                d=h>0&&c/h*h==c?1:d;
    return f;
}
like image 334
TheNumberOne Avatar asked Feb 20 '15 17:02

TheNumberOne


1 Answers

I've found a way to output the prime numbers without using System.out, FileDescriptor.out, or return. My method uses no "prime" characters.

This was very tricky, because e is all over the place in Java package names, class names, and method names. Also, S must be prohibited, because it's number 83 in Unicode, and 83 is prime. Its Unicode escape \u0053 contains a 5 whose Unicode character 53 is also prime. Here are all the characters we can't use a Unicode escape for under these rules:

  • % (37 is prime, \u0025 has a 5)
  • 5 (53 is prime, \u0035 has a 5)
  • S (83 is prime, \u0053 has a 5)
  • Y (89 is prime, \u0059 has a 5)
  • e (101 is prime, \u0065 has a 5)

This eliminated:

  • Any methods such as toString, fromString, parseInt, valueOf, and values.
  • java.beans, java.net, java.lang.reflect packages
  • Class.forName
  • Use of the new operator.
  • Logging frameworks that usually use a Logger class that contains e.

Here are characters for which we can use Unicode escapes:

  • ) (41 is prime, \u0029 is allowed)
  • + (43 is prime, \u002b is allowed)
  • / (47 is prime, \u002f is allowed)
  • ; (59 is prime, \u003b is allowed)
  • = (61 is prime, \u003d is allowed)
  • C (67 is prime, \u0043 is allowed)
  • G (71 is prime, \u0047 is allowed)
  • I (73 is prime, \u0049 is allowed)
  • O (79 is prime, \u004f is allowed)
  • a (97 is prime, \u0061 is allowed)
  • k (107 is prime, \u006b is allowed)
  • q (113 is prime, \u0071 is allowed)

Attempting to generate an exception whose message contains the desired output is the only way to fulfill the requirement in Java. We cannot use a checked exception, because just about all checked exceptions I could find use an e in their name, and in every superclass up through Throwable. I would be required to use a throws clause that included an exception name that contained an e. I couldn't extend any classes, because extends contains es.

That leaves unchecked exceptions. The most likely use would be an IllegalArgumentException that is created not by this code directly, but by a call to something built-in that throws an IllegalArgumentException.

  • Enums would have helped, except valueOf contains an e.
  • javax.crypto.Mac.getInstance has an e; it throws a checked exception anyway.
  • javax.naming.ldap.Rdn.unescapeValue("\\b" + stringFormOfOutput) outputted the list via an exception, but the method has an e.
  • java.util.UUID.fromString outputted the list via an exception, but the method has a S.

This method throws a DataBindingException which is unchecked.

  • javax.xml.bind.JAXB.unmarshal(stringFormOfOutput, Long.class) outputted the list via a DataBindingException, without an e.

Now all we have to do is convert the int[] to a String. String conversion by concatenating the array to "" doesn't work, because arrays, as objects in Java, don't override toString(). Arrays.toString is out because of the S.

We can use Arrays.asList to get a List out of the data. But Arrays.asList(f) gives a List<int[]>, not a List<Integer>, compounding the problem. Changing the type of f to Integer[] won't work, that has an e. Changing the type of f to Long[] works.

The conversion of the array to a String is as follows.

Long c,d,f[]...
""+Arrays.asList(f)

In place of the return statement, make the method void, and call unmarshal. The use of Long means a few other adjustments are necessary, such as using long literals and filling the array with zeros instead of the default nulls.

void b(int b){
    Long c,d,f[]={};
    for(f=java.util.Arrays.copyOf(f,b),Arrays.fill(f,0L);b-->0;)
        for(d=0L,c=2L;f[b]<1;f[b]=d<1?c:f[b],d=0L,c++)
            for(long h:f)
                d=h>0&&c/h*h==c?1:d;
    javax.xml.bind.JAXB.unmarshal(""+Arrays.asList(f),Long.class);
}

Escaping the "prime" characters:

void b(int b\u0029{
    Lon\u0067 c,d,f[]\u003d{}\u003b
    for(f\u003dj\u0061v\u0061.util.Arr\u0061ys.copy\u004ff(f,b\u0029,Arr\u0061ys.fill(f,0L\u0029\u003bb-->0\u003b\u0029
        for(d\u003d0L,c\u003d2L\u003bf[b]<1\u003bf[b]\u003dd<1?c:f[b],d\u003d0L,c\u002b\u002b\u0029
            for(lon\u0067 h:f\u0029
                d\u003dh>0&&c\u002fh*h\u003d\u003dc?1:d\u003b
    j\u0061v\u0061x.x\u006dl.bind.JAXB.un\u006d\u0061rsh\u0061l(""\u002bArr\u0061ys.\u0061sList(f\u0029, Lon\u0067.cl\u0061ss\u0029\u003b
}

This is ugly code, and it probably won't win any code-golfing contests, but it is the only way I can think of in Java to fulfill the requirements.

Calling this b method with 10 as an argument yields the following output, with [29, 23, 19, 17, 13, 11, 7, 5, 3, 2] being the first 10 primes:

Exception in thread "main" javax.xml.bind.DataBindingException: javax.xml.bind.UnmarshalException
 - with linked exception:
[java.io.FileNotFoundException: C:\dev\src\misc\[29, 23, 19, 17, 13, 11, 7, 5, 3, 2] (The system cannot find the file specified)]
    at javax.xml.bind.JAXB.unmarshal(JAXB.java:208)
    at Main.b(Main.java:34)
    at Main.main(Main.java:12)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
Caused by: javax.xml.bind.UnmarshalException
 - with linked exception:
[java.io.FileNotFoundException: C:\dev\src\misc\[29, 23, 19, 17, 13, 11, 7, 5, 3, 2] (The system cannot find the file specified)]
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:206)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:181)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:235)
    at javax.xml.bind.JAXB.unmarshal(JAXB.java:205)
    ... 7 more
Caused by: java.io.FileNotFoundException: C:\dev\src\misc\[29, 23, 19, 17, 13, 11, 7, 5, 3, 2] (The system cannot find the file specified)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:97)
    at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90)
    at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:609)
    at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:189)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:799)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
    ... 10 more

But what about public static void main(String[] args)? There is a seemingly unavoidable S. Make b static and call b with a static initializer, to eliminate main and its String[] requirement.

st\u0061tic
{
   b(10\u0029\u003b
}

st\u0061tic void b(int b\u0029{
// ...

The output now contains an ExceptionInInitializerError, but the rest of the output is intact; the DataBindingException is chained.

Exception in thread "main" java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:190)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:87)
Caused by: javax.xml.bind.DataBindingException: javax.xml.bind.UnmarshalException
 - with linked exception:
[java.io.FileNotFoundException: C:\dev\src\misc\[29, 23, 19, 17, 13, 11, 7, 5, 3, 2] (The system cannot find the file specified)]
    at javax.xml.bind.JAXB.unmarshal(JAXB.java:208)
...
like image 135
rgettman Avatar answered Nov 15 '22 03:11

rgettman