Java 9/10 and macOS – issues with java.version

It looks like you have to be extra careful while working with recent releases of JDK for macOS.

If you want to get JVM’s version (while running application) there is a simple way of doing it.

public class Simple {
  public static void main(String [] args) {
    System.out.println(System.getProperty("java.version"));
  }
}

However, you have to be extra careful in macOS. For JVM 9 and JVM 10 you will get “9” and “10” respectively. This might be an issue, especially when you parse the version String to get major/minor numbers

String version = System.getProperty("java.version");

// this will give you -1 (for JVM 9/10), and that's no good
int dotPos = version.indexOf('.');

The funny thing is, that moving to 10.0.2 will suddenly give you different format (proper one).

In fact, there is a completely new way of getting JVM version since release 9 – Runtime.version(). And this one, will give all the information you need.

public class Simple {
  public static void main(String [] args) {
    System.out.println(System.getProperty("java.version"));
    Runtime.Version jvmversion = Runtime.version();
    System.out.println("major: " + jvmversion.major() 
      + " minor: " + jvmversion.minor() 
      + " security: " + jvmversion.security());
  }
}

which will give you

9
major: 9 minor: 0 security: 0

bash 4.4 on macOS

# Get the sources

mkdir -p ~/opt/src
cd ~/opt/src
curl -O http://ftp.gnu.org/gnu/bash/bash-4.4.tar.gz
tar zxf bash-4.4.tar.gz

# prepare place for installation
mkdir -p ~/opt/usr

# build the stuff
cd ~/opt/src/bash-4.4
./configure --prefix=$HOME/opt/usr
make
make install

# test the thing
$HOME/opt/usr/bin/bash --version

use it

#!/Users/your_user_name/opt/usr/bin/bash

echo $BASH_VERSION

So, you are telling me that you can distinguish colors ;)

Colors can be source of real fight between people. There is even dedicated chapter related to colors in book “Jak przestałem kochać design” by Marcin Wicha. If you want people to kill you, try the list below whenever you want to apply small changes to web page UI ;)

> colors()
  [1] "white"                "aliceblue"            "antiquewhite"         "antiquewhite1"       
  [5] "antiquewhite2"        "antiquewhite3"        "antiquewhite4"        "aquamarine"          
  [9] "aquamarine1"          "aquamarine2"          "aquamarine3"          "aquamarine4"         
 [13] "azure"                "azure1"               "azure2"               "azure3"              
 [17] "azure4"               "beige"                "bisque"               "bisque1"             
 [21] "bisque2"              "bisque3"              "bisque4"              "black"               
 [25] "blanchedalmond"       "blue"                 "blue1"                "blue2"               
 [29] "blue3"                "blue4"                "blueviolet"           "brown"               
 ...
 ...                          
[625] "thistle"              "thistle1"             "thistle2"             "thistle3"            
[629] "thistle4"             "tomato"               "tomato1"              "tomato2"             
[633] "tomato3"              "tomato4"              "turquoise"            "turquoise1"          
[637] "turquoise2"           "turquoise3"           "turquoise4"           "violet"              
[641] "violetred"            "violetred1"           "violetred2"           "violetred3"          
[645] "violetred4"           "wheat"                "wheat1"               "wheat2"              
[649] "wheat3"               "wheat4"               "whitesmoke"           "yellow"              
[653] "yellow1"              "yellow2"              "yellow3"              "yellow4"             
[657] "yellowgreen" 

Unit Testing iPhone Apps – picture is worth a thousand words

If you are looking for well prepared, well delivered (unfortunately little bit outdated) video training on Unit Testing, make sure to watch this one

In case you still struggle with some old Objective-C based code, this one might be a good choice when you want to move old stuff towards TDD approach.

You can read my review here: Unit Testing iPhone Apps by Dan Pilone and Courtney Nash


vi + which

Sometimes, you want to look at the command (where is it located), and then, you decide to actually take a look inside the file (e.g. script). Instead of copying and pasting location, do following

which perl
vi `!!`

Escape Java/XML

mkdir escapefromreality
mkdir lib
echo 'package escapefromreality;

import java.io.File;
import org.apache.commons.io.FileUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.commons.text.StringEscapeUtils.Builder;

public class EscapeJavaCode {

  public static void main(String[] args) throws Exception {
    try {
      String strJava = FileUtils.readFileToString(new File("escapefromreality/EscapeJavaCode.java"));
      System.out.println(
        StringEscapeUtils.builder(StringEscapeUtils.ESCAPE_JAVA)
          .escape(strJava)
          .toString()
      );

      String strXML = FileUtils.readFileToString(new File("sample.xml"));
      System.out.println(
        StringEscapeUtils.builder(StringEscapeUtils.ESCAPE_XML11)
          .escape(strXML)
          .toString()
      );
    } catch(Exception ex) {
      // remember to handle the exception
    }
  }
}' > escapefromreality/EscapeJavaCode.java

echo '<xml>
  <sample attr="Hello"/>
  <![CDATA[Some CDATA
  section
  ]]>
</xml>' > sample.xml


curl -O http://ftp.man.poznan.pl/apache//commons/text/binaries/commons-text-1.4-bin.tar.gz
tar zxf commons-text-1.4-bin.tar.gz \
  --strip-components=1 \
  -C lib/ \
  commons-text-1.4/commons-text-1.4.jar

curl -O http://ftp.man.poznan.pl/apache//commons/io/binaries/commons-io-2.6-bin.tar.gz
tar zxf commons-io-2.6-bin.tar.gz \
  --strip-components=1 \
  -C lib/ \
  commons-io-2.6/commons-io-2.6.jar

curl -O http://ftp.ps.pl/pub/apache//commons//lang//binaries/commons-lang3-3.7-bin.tar.gz
tar -zxf commons-lang3-3.7-bin.tar.gz \
  --strip-components=1 \
  -C lib/ \
  commons-lang3-3.7/commons-lang3-3.7.jar

javac -cp lib/commons-text-1.4.jar:lib/commons-io-2.6.jar \
  escapefromreality/EscapeJavaCode.java

for filename in lib/*.jar; do
  CP=${CP}:${filename}
done

java -cp .:${CP} escapefromreality/EscapeJavaCode


You shouldn’t learn Vim for learning’s sake

I can see people around (on various blogs) saying “- I’ve never used Vim before, and it’s so cool. I really have to learn how to use Vim!”.

Just Don’t.

If you are using IntelliJ, NetBeans, Visual Studio, Eclipse, keep it that way. Don’t put yourself into this illusive thinking that by starting using Vim you will become some sort of expert or something.

The only situation in which learning Vim may be regarded useful is when you plan to work on CLI – a lot. That’s it. There are no other reasons.

So, ask yourself honestly “- Will I spend 3/4th of my day while working on some remote UNIX machine, using CLI all the time?”. If your answer is “- No, I won’t”, stick to the IDE you already know and don’t waste time on Vim. Learn something else.

However! If you really, really want to learn it. Make sure to look here: Mastering Vim and Learning vi and Vim editors also, take a look at Tuvim ;)

Slightly different point of view: Why Vim?


Coding time flies when you’re having fun

AAEAAQAAAAAAAAaOAAAAJGRiOWM1ZDJlLWJkNWUtNDgzOS1hODE4LTY2ZWRhY2EyYWNkNA

Everything should be kept as simple as possible, but no simpler.

Teaching kids is a hard work. By teaching I mean not lecturing, but real, efficient and full of fun explaining how things work. I still remember one of my first computer languages – LOGO. This was Atari time and we have learned principles of programming by learning how turtle works. It was fun, but at the same time, it had lots of limitations.

First of all, if you want to write LOGO code you have to know how to write. You have to type on the keyboard, and you have to pay lots of attention to syntax. And, to be honest, LOGO code isn’t that sexy.

You can “penup”, you can “pendown” and move around. Of course you can do a lot with LOGO, but let’s face it, having fun with LOGO requires lots of work to be done.

The limits of my language means the limits of my world.

If you want to teach kids computer programming, you should start with something that allows expressing relatively complex ideas using simple language. In my opinion, at the time of writing, Scratch is exactly this kind of language.

Power of Scratch lays in the simplicity of code building mixed with quick reward. You can make objects move on the screen with just few clicks. Let’s play small quiz – just to show a sample.

Quiz time: What can you do, using following elements

Well, you can do pretty much. You can develop simple game and this way let the kids understand basics of programming.

Teaching coding is a hard task. If you want to avoid typical “Hello world” approach while delivering lectures to kids, you should become familiar with Scratch. It pays off.


TIS-100 – nice brain teaser for people
who like Assembler

If you like brain teasers, there is this cool game: TIS-100.

It’s a game, where you are supposed to solve Assembler based problems. You have a reduced set of instructions: moving data, basic arithmetics, few conditional jumps, and only one register – ACC. Well, in fact there are two registers, but other one is only accessible via ACC. In early stages you don’t have neither memory not the stack. Port operations are blocking, so you have to make sure things goes smoothly between modules.

What I have found most funny for me, was that kind of feeling related to missing elements coming from “normal/typical” architectures. I missed all these simple elements like stack, numerous registers, memory. Once you start playing, you need to change typical, assembler based, approach as you work with heavily reduced architecture. Another limitation is that each node (where you can run the code) has 15 lines limit and, sometimes, you have to pass data to other module to make intermediate calculations.

Anyway, this game is a real fun if you like low level coding. Learning architecture and getting used to instructions set will take you approximately 15-30 minutes. And here, Hacker’s Guide, you can find very well prepared cheat sheet for TIS-100.

The game is really worth the money – it’s just 12 PLN this week (during Steam Summer Sale).


Killing all your VNC sessions at once

#!/bin/bash

SESSIONS_NO=`vncserver -list | grep "^:" | tr '\t' ' ' | cut -f1 -d' ' | wc -l`

if [[ $SESSIONS_NO -ne 0 ]]; then
  for no in $(vncserver -list | grep "^:" | tr '\t' ' ' | cut -f1 -d' '); do
    vncserver -kill $no
  done
else
  echo "There are no running VNC sessions for user: $USER"
fi

Pegasus Workflow Management System + VMware Fusion

If you want to start your experience with Pegasus Workflow Management System I strongly advice to use ready to go Virtual Machine available for download. You can get it here.

PegasusTutorialVM-4.7.4.ova

After downloading it, open VMware Fusion and choose: File -> Import… and choose PegasusTutorialVM-4.7.4.ova (you can find it wherever you have stored it – probably inside Downloads). After choosing the file, you will see something like this

Press Continue. VMware Fusion will complain!

Don’t worry, it will import machine properly, eventually. Simply press Retry. After a while, you will be notified that import was finished.

Fusion may complain about upgrading machine to reflect most recent changes in your release. Feel free to upgrade your machine. Press: Upgrade.

After a while, you will be shown a clock on nice blue background. Just drag it and scroll up. Now, you are ready to log in into machine. Chose user tutorial and type in pegasus as password.

On the left side of screen you will find Terminal application. Double click it. Now, it is the time to start your first task. Go ahead and create your first task.


Do not give up. Fight till the end.

I was supposed to say

This is the end
Beautiful friend
This is the end
My only friend, the end
— The Doors, The End

after seeing this beautiful picture during startup.

As you may guess, it was gone. Everything was gone. Apart from data: “- Thank you! My dear Backup System, thank you. I owe you! Again!”

Anyway. I was 100% sure it was broken GPU. At least that’s what all the Internet was saying. However, I wanted to check my system once again. Just to be sure. All I had to do was pressing

D

while starting up. I have performed full test (it lasted for more than few hours) and then … it worked. My system started as usual. Of course I had to recover from data loss, but that’s just a minor issue ;)


Java, Python and IO inheritance

If you remember old way of reading/writing streams between JVM and external process, you probably remember how tedious it was in the past (all these Gobblers, Threads, etc.). Today, it’s way more simple. All you have to do, is inheriting JVM’s IO.

Let’s say you want to run simple Python code that reads something from input stream.

value = raw_input("Type the number? ")
print "Your number is: " + value

all you have to do is to call it from ProcessBuilder and inherit the IO.

public class PythonProcess {
  public static void main(String [] arg) throws Exception {
    ProcessBuilder pb =
      new ProcessBuilder("python", "script.py").inheritIO();
    Process p = pb.start();
    p.waitFor();
  }
}

After this is done you can simply run the code

> javac PythonProcess.java
> java -cp . PythonProcess
Type the number? 44
Your number is: 44

macOS High Sierra – make sure your system is safe
updated for ClamAV release 0.100.0

If you want to make sure that your macOS High Sierra is clean (when it comes to malicious software) you can use free tool (free as in beer and free as in speech – at the same time) called ClamAV.

You can get it various ways. You can download it’s commercial version from AppStore – as paid release, you can install it using brew, download binary from some place where you have no idea what’s really inside, You can instal macOS Server (ClamAV comes bundled with it), etc.

However, you can also build it by yourself. Directly from sources. It’s a pain in a neck, I know, but you can be sure of what you are actually running. And, you will learn that zlib’s library author is a really brainy person. Go ahead, look for yourself in Wikipedia.

Anyway. Let’s start. Estimated time to complete (depending on your system configuration) – 1h-2h.

I suggest to create some place, where you can put all sources and binaries. I suggest following approach

mkdir -p $HOME/opt/src
mkdir -p $HOME/opt/usr/local

In each step, we will download source codes of given tool into

$HOME/opt/src

and then, use

./configure --prefix=$HOME/opt/usr/local/$TOOL_NAME

to install them inside $HOME/opt.

1. You need PCRE – Perl Compatible Regular Expressions

cd $HOME/opt/src
curl -O ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre2-10.30.tar.gz
tar zxf pcre2-10.30.tar.gz
cd pcre2-10.30
./configure --prefix=$HOME//opt/usr/local/pcre2
make
make install

# You can also run `make check` before installing PCRE, but you may need to apply path
# source: https://bugs.exim.org/attachment.cgi?id=1031&action=diff
#
# To apply it, simply put patch content inside file RunGrepTest.fix
#
#
# --- 8< --- CUT HERE --- 8< --- CUT HERE --- 8< --- CUT HERE --- 8< --- 
--- RunGrepTest	2017-07-18 18:47:56.000000000 +0200
+++ RunGrepTest.fix	2018-01-07 20:00:40.000000000 +0100
@@ -681,7 +681,7 @@
 # works.

 printf "%c--------------------------- Test N7 ------------------------------\r\n" - >>testtrygrep
-if [ `uname` != "SunOS" ] ; then
+if [ `uname` != "Darwin" ] ; then
   printf "abc\0def" >testNinputgrep
   $valgrind $vjs $pcre2grep -na --newline=nul "^(abc|def)" testNinputgrep | sed 's/\x00/ZERO/' >>testtrygrep
   echo "" >>testtrygrep
# --- 8< --- CUT HERE --- 8< --- CUT HERE --- 8< --- CUT HERE --- 8< ---
#
# and run patch tool
# 
patch -b RunGrepTest RunGrepTest.fix

2. You need LibreSSL
(special thanks go to: http://www.gctv.ne.jp/~yokota/clamav/). I was always using OpenSSL, but recently I had more and more issues with it while compiling stuff from sources.

cd $HOME/opt/src
curl -O https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.6.4.tar.gz
tar zxf libressl-2.6.4.tar.gz
cd libressl-2.6.4
export CXXFLAGS="-O3"
export CFLAGS="-O3"
./configure --prefix=$HOME/opt/usr/local/libressl
make
make check
make install

3. You need zlib

cd $HOME/opt/src
curl -O http://zlib.net/zlib-1.2.11.tar.xz
tar zxf zlib-1.2.11.tar.xz
cd zlib-1.2.11
./configure --prefix=$HOME/opt/usr/local/zlib
make
make install

4. Build the stuff

cd $HOME/opt/src
git clone git://github.com/vrtadmin/clamav-devel
cd clamav-devel
git checkout tags/clamav-0.100.0 -b rel/0.100
# you can also get stable version from here:
# https://www.clamav.net/downloads
export CFLAGS="-O3 -march=nocona"
export CXXFLAGS="-O3 -march=nocona"
export CPPFLAGS="-I$HOME/opt/usr/local/pcre2/include \
  -I$HOME/opt/usr/local/libressl/include \
  -I$HOME/opt/usr/local/zlib/include"
./configure --prefix=$HOME/opt/usr/local/clamav --build=x86_64-apple-darwin`uname -r` \
  --with-pcre=$HOME/opt/usr/local/pcre2 \
  --with-openssl=$HOME/opt/usr/local/libressl \
  --with-zlib=$HOME/opt/usr/local/zlib \
  --disable-zlib-vcheck \
make
make install

5. Make sure to keep your database up to date

$HOME/opt/usr/local/clamav/bin/freshclam

6. Now, you can scan your drive for viruses

cd $HOME
$HOME/opt/usr/local/clamav/bin/clamscan --log=$HOME/scan.log -ir $HOME

# if you want to scan your whole drive you need to run the thing as root
# I also suggest to exclude /Volumes, unless you want to scan your TimeMachine
# and all discs attached
# -i - report only infected files
# -r - recursive
# --log=$FILE - store output inside $FILE
# --exclude=$DIR - don't scan directory $DIR
cd $HOME
sudo $HOME/opt/usr/local/clamav/bin/clamscan --log=`pwd`/scan.log --exclude=/Volumes --exclude=/tmp -ir /

To compile ClamAV on macOS High Sierra I have used my old scripts, but many thanks go to: http://www.gctv.ne.jp/~yokota/clamav


Simple automation for random commenter name

$input_1 = array(
  "Pragmatyzm",
  "Idealizm",
  "Sofizm",
  "Arystotelizm",
  "Scholastyka",
  "Egzystencjalizm",
  "Fenomenologia",
  "Analityka",
  "Behawioryzm",
  "Buddyzm",
  "Kartezjanizm"
);

$input_2 = array(
  "Kanta",
  "Arystotelesa",
  "Platona",
  "Sokratesa",
  "Kartezjusza",
  "Peirce'a",
  "Dennetta",
  "Kołakowskiego",
  "Tatarkiewicza",
  "Kotarbińskiego",
  "Kanta",
  "Locke'a"
);

$name = $input_1[rand(0, count($input_1) - 1)] . ' ' . $input_2[rand(0, count($input_2) - 1)];
		
<input 
  hidden="true" 
  type="text" 
  name="author" 
  id="author" 
  class="text" 
  value="<?php echo htmlspecialchars($name)?>"/>

GDPR and blog comments

I have no idea whether GDPR affects personal blogs or not.

However, I decided to clean all the e-mails attached to comments, anyway. In fact, I haven’t asked people for name, e-mail, anything, for quite some time (more than a year already, I guess).

Today, however, I have decided to make a final step. I don’t store anything.

You will be given random name (whenever you want to comment something), I don’t want to know your IP address, and I have no interest in knowing your e-mail. Just express yourself in comment field ;)

If you are looking for GDPR ready SQL query for Word Press, here it is

update 
  wp_comments
set
  comment_author='anonymous',
  comment_author_email='anonymous@e-mail.com',
  comment_author_url='localhost',
  comment_author_IP='127.0.0.1';

I’d love to comment an article on your blog

but you don’t let me do it. Dear, anonymous blogger, you make me run away just after reading your ideas.

Yes, you hide yourself behind Disqus, Twitter, Facebook login. You force me to provide my name, my e-mail, my everything. It makes me say “-I don’t care. Reading was nice, but I have no time for all that login stuff”. And I quit. I haven’t given you any feedback, even though I wanted to say “-Thanks man! It was a really nice read! Keep up good work.”

So, maybe you can just get rid of all that “log in to comment” stuff? Just turn moderation on, add some spam filter, that’s it.


Unpacking RPM

rpm2cpio file.rpm | cpio -idmv

It looks like all the people in IT industry write books …

and this reminds me of a quote

The irresistible proliferation of graphomania among politicians, taxi drivers, childbearers, lovers, murderers, thieves, prostitutes, officials, doctors, and patients shows me that everyone without exception bears a potential writer within him, so that the entire human species has good reason to go down into the streets and shout: “We are all writers!” (…) One morning (and it will be soon), when everyone wakes up as a writer, the age of universal deafness and incomprehension will have arrived.

– Milan Kundera, The Book of Laughter and Forgetting, 1978

Are we there yet?


Story of a simple task

There was this on-line challange where you were supposed to calculate the cargo that could fit into your cargo space. Task, itself, was not complicated, however my ideas about solving it, were jumping from technology to technology. From purely functional, via object based to ancient, structural based, approach.

At first, I though – “Why not use Scala or something? All this new functional fuss. It will be super cool”. I have created all possible lists of cargo with toSet and subsets, ordered lists by cargo size and price. Then, I have thrown away cargo that doesn’t fit, and taken head. At this point, I could have easily refer to List of tuples that define the best match. Nice!

def foldTuples(l: List[List[(Int,Int)]]): List[(Int,Int,Int)] = {
  def _foldTuples(res: List[(Int,Int,Int)], rem: List[List[(Int,Int)]], idx: Int):
  List[(Int,Int,Int)] = rem match {
    case Nil => res
    case (h:List[(Int, Int)])::tail => _foldTuples(
      res:+h.foldLeft(
        (0,0,idx)){(acc,iter) => (acc._1 + iter._1, acc._2 + iter._2, idx)}, 
      tail, 
      idx+1)
  }
  _foldTuples(List.empty[(Int,Int, Int)], l, 0)
}

var a = List((2,26),(6,30),(4,28),(4,36),(3,30)).
  toSet[(Int,Int)].subsets.map(_.toList).toList;
a(foldTuples(a).filter(_._1 <= 12).sortWith(_._2 > _._2).head._3)

But hey! Maybe OO based approach would be better here? I could have created Ship with a Cargo bay. Cargo bay could hold different kinds of Cargo represented by yet another class. This way, process of calculating cargo size would be hidden. It could be delegated to Cargo bay itself. In case like this, all I need to do to get my stuff packed is to ask the Ship: “-Hey, Falcon, here is the cargo. Will it fit in?”

import java.util.ArrayList;

public class Ship {

  public Ship(int cargoSize) {
    bay = new CargoBay(cargoSize);
  }

  public void fillCargoBay(ArrayList<Cargo> cargo) {
    bay.fill(cargo);
  }

  public void printCargo() {
    bay.printCargo();
  }

  public static void main(String[] arg) {
    ArrayList<Cargo> boxes = new ArrayList<>();
    boxes.add(new Cargo(2, 26));
    boxes.add(new Cargo(6, 30));
    boxes.add(new Cargo(4, 28));
    boxes.add(new Cargo(4, 36));
    boxes.add(new Cargo(3, 30));

    Ship millenniumFalcon = new Ship(12);
    millenniumFalcon.fillCargoBay(boxes);
    millenniumFalcon.printCargo();
  }

  private CargoBay bay;
}

class CargoBay {
  public CargoBay(int maxCapacity) {
    this.maxCapacity = maxCapacity;
  }

  public void fill(ArrayList<Cargo> cargo) {
    ArrayList<ArrayList> allSubSets = generateAllSubSets(cargo);

    Cargo currentMax = calculateCapacityOfCargo(this.cargo);

    for(ArrayList list : allSubSets) {
      Cargo nextCargo = calculateCapacityOfCargo(list);
      if(nextCargo.size <= maxCapacity && nextCargo.price > currentMax.price) {
        this.cargo = list;
        currentMax = nextCargo;
      }
    }
  }

  public void printCargo() {
    for(Cargo c : this.cargo) {
      System.out.println("size: " + c.size + " price: " + c.price);
    }
  }

  private Cargo calculateCapacityOfCargo(ArrayList<Cargo> cargo) {
    Cargo result = new Cargo(0, 0);
    for (Cargo c : cargo) {
      result.size += c.size;
      result.price += c.price;
    }
    return result;
  }

  private ArrayList<ArrayList> generateAllSubSets(ArrayList<Cargo> cargo) {

    ArrayList<ArrayList> cargoLists = new ArrayList<>();

    int n = cargo.size();

    for (int i = 0; i < (1 << n); i++) {
      ArrayList<Cargo> newCargo = new ArrayList<>();
      for (int j = 0; j < n; j++) {
        if ((i & (1 << j)) > 0) {
          newCargo.add(cargo.get(j));
        }
      }
      cargoLists.add(newCargo);
    }
    return cargoLists;
  }

  private ArrayList<Cargo> cargo = new ArrayList<Cargo>();
  private int maxCapacity = 0;
}

class Cargo {
  public Cargo(int size, int price) {
    this.price = price;
    this.size = size;
  }

  public int size;
  public int price;
}

Nah, man. OO based result is way too long. But, wait! Maybe there is a different way? Maybe I can do it nasty, structural, way? Is it possible to create something that will fit inside one Tweet? Yes it is. Here comes the code. Simple, small, and very elegant ;) It has recursion, have you noticed? Thus, it must be a sophisticated one ;)

crg[]={2,26,6,30,4,28,4,36,3,30,12},mp,mm;
int l(i,c,p,m){return (i<5)
?(l(i+1,c,p,m)&&l(i+1,c+(i*2)[crg],p+(i*2+1)[crg],m|=(1<<i)))
:((p>mp && c<=10[crg])?((mp=p)&&(mm=m)):1);}
int main(){l(0,0,0,0);
for(int i=0;i<5;i++)mm&(1<<i)
?printf("%d,%d\n",(i*2)[crg],(i*2+1)[crg])
:0;}

And it fits in a one Tweet ;)


←Older