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 e
s.
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
.
Enum
s 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 fill
ing the array with zeros instead of the default null
s.
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)
...