MonthSeptember 2010

Matrix I/O in PHP 5.3

Inspired by the Grid Computing challenge at Code Golf, I came up with a couple of useful functions for reading and writing matrices in PHP 5.3

<?php

/**
 * Returns the array of rows by columns whose values are from the given matrix.
 * NOTE: white space is discarded.
 *
 * @param string $matrix (example)
 * '
 *         A, B,  C, D,    E
 *       FFF, G,  H, I,    J
 *         K, L, MM, N,    P
 *         Q, R,  S, T, UUUU
 *     VVVVV, W,  X, Y,    Z
 * ';
 * @param array $glue
 *   rows => string, separator that glues rows together
 *   cols => string, separator that glues columns together
 * @return array (example)
 * array(
 *     array(    'A', 'B',  'C', 'D',    'E',),
 *     array(  'FFF', 'G',  'H', 'I',    'J',),
 *     array(    'K', 'L', 'MM', 'N',    'P',),
 *     array(    'Q', 'R',  'S', 'T', 'UUUU',),
 *     array('VVVVV', 'W',  'X', 'Y',    'Z',),
 * );
 */
function matrixToRowsByColumns($matrix, $glue = array('rows' => "\n", 'cols' => ','))
{
    $result = array_map(function($row) use ($glue)
    {
        return array_map('trim', explode($glue['cols'], $row));
    }, explode($glue['rows'], trim($matrix)));
    return $result;
}

/**
 * Returns the array of rows by columns whose rows and columns are the columns
 * and rows respectively of the given array of rows by columns
 *
 * @param array $rows (example)
 * array(
 *     array(    'A', 'B',  'C', 'D',    'E',),
 *     array(  'FFF', 'G',  'H', 'I',    'J',),
 *     array(    'K', 'L', 'MM', 'N',    'P',),
 *     array(    'Q', 'R',  'S', 'T', 'UUUU',),
 *     array('VVVVV', 'W',  'X', 'Y',    'Z',),
 * );
 * @return array (example)
 * array(
 *     array('A', 'FFF',  'K',    'Q', 'VVVVV',),
 *     array('B',   'G',  'L',    'R',     'W',),
 *     array('C',   'H', 'MM',    'S',     'X',),
 *     array('D',   'I',  'N',    'T',     'Y',),
 *     array('E',   'J',  'P', 'UUUU',     'Z',),
 * );
 */
function transpose($rows)
{
    $result = call_user_func_array('array_map', array_merge(array(null), $rows));
    return $result;
}

/**
 * Returns the matrix whose values are from the given array of rows by columns.
 *
 * @param array $rows (example)
 * array(
 *     array(    'A', 'B',  'C', 'D',    'E',),
 *     array(  'FFF', 'G',  'H', 'I',    'J',),
 *     array(    'K', 'L', 'MM', 'N',    'P',),
 *     array(    'Q', 'R',  'S', 'T', 'UUUU',),
 *     array('VVVVV', 'W',  'X', 'Y',    'Z',),
 * );
 * @param array $glue
 *   rows => string, separator that glues rows together
 *   cols => string, separator that glues columns together
 * @param string $leadingWhite indentation of the matrix
 * @return string (example)
 * '
 *         A, B,  C, D,    E
 *       FFF, G,  H, I,    J
 *         K, L, MM, N,    P
 *         Q, R,  S, T, UUUU
 *     VVVVV, W,  X, Y,    Z
 * ';
 */
function rowsByColumnsToMatrix($rows, $glue = array('rows' => "\n", 'cols' => ','), $leadingWhite = '    ')
{
    $format = array_map(function ($row)
    {
        $max = max(array_map('strlen', $row));
        return '%'. $max .'s';
    }, transpose($rows));
    $format = $leadingWhite . implode($glue['cols'] . ' ', $format);
    $format = array_fill(0, count($rows), $format);
    $format = implode($glue['rows'], $format);
    $result = call_user_func_array('array_merge', $rows);
    $result = call_user_func_array('sprintf', array_merge(array($format), $result));
    $result = "$glue[rows]$result$glue[rows]";
    return $result;
}

Here is a demo page

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html> 
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
        <title></title> 
    </head> 
    <body> 
        <pre> 
<?php 
require_once 'matrix.php'; 
 
$input = ' 
        A, B,  C, D,    E 
      FFF, G,  H, I,    J 
        K, L, MM, N,    P 
        Q, R,  S, T, UUUU 
    VVVVV, W,  X, Y,    Z 
'; 
$rows = matrixToRowsByColumns($input); 
//$rows = transpose($rows); 
$output = rowsByColumnsToMatrix($rows, array('rows' => " \n", 'cols' => ','), '    '); 
 
$input  = var_export($input, true); 
$output = var_export($output, true); 
 
echo "<hr>\$input = $input;"; 
echo "<hr>\$output = $output;"; 
echo '<hr>$output ' . ($output === $input ? '=' : '!') . '== $input'; 
?> 
        </pre> 
    </body> 
</html>

whose result is

 

$input = ' A, B, C, D, E FFF, G, H, I, J K, L, MM, N, P Q, R, S, T, UUUU VVVVV, W, X, Y, Z ';
$output = ' A, B, C, D, E FFF, G, H, I, J K, L, MM, N, P Q, R, S, T, UUUU VVVVV, W, X, Y, Z ';
$output === $input

After uncommenting the transposition line, the result is

 

$input = ' A, B, C, D, E FFF, G, H, I, J K, L, MM, N, P Q, R, S, T, UUUU VVVVV, W, X, Y, Z ';
$output = ' A, FFF, K, Q, VVVVV B, G, L, R, W C, H, MM, S, X D, I, N, T, Y E, J, P, UUUU, Z ';
$output !== $input

WordPress on Chrome has the messiest editing bug

I found this bug recently, and there seems to be very little evidence of it in Internet.

I have the last versions of WordPress, Chrome, and WinXP. When editing a post in Visual mode, if I write normal text, all is well, and if I change to HTML mode and back to Visual, all is fine too. But if I click the bullet list (or number list) button in a paragraph, the bug is reproduced: the path at the left bottom corner of the editing box says “Path: ul li span”.

This additional span has a style that sets the size of the font to 13.3333px !!

The formatting, as seen in the HTML mode, is:

And if I undo the bullet list (or number list), it becomes:

The real nasty things about this bug are:

  1. It doesn’t show up in Firefox (the most common default browser among web developers)
  2. It’s pretty common, but almost nobody noticed it
  3. It shows up when doing/undoing a bullet list or a number list
  4. The bug adds ghost spans, one per item, that you must remove manually (like in the following entry)
  5. And manually means manually in HTML mode, because in Visual mode, the “Remove formatting” button usually removes too much formatting
  6. The bug is so strong that if you remove the ghost spans and then undo a list, the same number of ghost spans are added back again
  7. If you don’t remove the garbage as you go, it gets messier and messier, because the ghost spans start to appear also where never there has been a list
  8. I wasn’t able to find where the bug comes from: a search of all WordPress code returns nothing interesting

I’ll look at my theme and plugins code.

For now, it’s a filed bug.

Wrong Assumptions

A couple of weeks ago I needed a mind mapping software and tried some of the free packages.

Xmind was the best one for me. I really liked the fact that with very little effort I got good looking maps.
This allows me to concentrate on the domain concepts I’m trying to model instead of representation details.

When opening Xmind today, I’ve been notified of a new version (3.2.0), so I downloaded and installed it. After opening Xmind again, I found that my English application had turned to Spanish. Spanish translations use to be very bad (and this is not an exception), so I prefer English ones.

Well, I thought, no problem, I’ll go for the config option and change the app back to English. But there is no config option!! So I went back to the site to find out what was going on. In the download page they say:

Every package now contains 7 language packs, English English, GermanGerman, French French, Spanish Spanish, Japanese Japanese, Chinese(Simplified) Chinese(Simplified), and Chinese(Traditional) Chinese(Traditional). XMind will choose language automatically to fit your OS’s settings. Changing your OS’s language settings will change XMind too.

That’s unbelievable!! Do I need to change a global option for changing a local one?

So, here goes my hack, for getting back to English.

  • Edit the file (Xmind folder) configuration org.eclipse.equinox.simpleconfigurator bundles.info and comment out any line that refers to a Spanish translation (containing nl_es).

    Notepad++ Replace dialog for Xmind language hack

When you restart Xmind, English is back.

Is Rails clever or smart?

When generating a Rails project you can specify the database adapter. If you select mysql, then Rails 3.0.0 translates mysql to mysql2, which is (or should be) the current adapter for MySQL in Ruby.

I smell a hack here, like a solution belonging elsewhere.

Problem: A new MySQL adapter is available, so how do we make Rails compatible with it?

Clever solution: We translate mysql to mysql2, so that any time a user requests the old mysql adapter, the new mysql2 adapter will be used instead.

Smart solution: We add mysql2 alongside mysql, so that Rails users will decide which adapter they want.

I think that Rails implemented the clever solution because there are Rails developers that write applications in IDEs, which are released infrequently. Those developers would have to wait a lot to get the new mysql2 adapter accessible from their IDEs. So, a transparent translation is very effective in this case, because an IDE dialog for generating a project will execute the “rails new” command under the hood, requesting the mysql adapter. The problem is that there’s no way to use the old mysql adapter, if a Rails developer really wants to, except for hacking Rails itself.

Anyway, I think that Rails could have been smarter. When the user issues the “rails new” command, these are the possible combinations:

  1. mysql2 is installed but mysql is not
    If the user specifies “–database=mysql”, Rails should inform: “using available mysql2 adapter instead of specified mysql”, thus translating mysql to mysql2. This takes care of the fact that mysql2 is meant to replace mysql.
    If the user specifies “–database=mysql2”, Rails should use the specified adapter.
  2. mysql is installed but mysql2 is not
    If the user specifies “–database=mysql”, Rails should use the specified adapter.
    If the user specifies “–database=mysql2”, this should be considered an error and Rails should stop and inform the user. This takes care of the fact that mysql2 has been released after mysql.
  3. neither mysql2 nor mysql are installed
    If the user specifies “–database=mysql” or “–database=mysql2”, this is an error and Rails should stop and inform the user.
  4. both mysql2 and mysql are installed
    If the user specifies “–database=mysql” or “–database=mysql2”, Rails should use the specified adapter.

Browsing Rails code, I see that they were implementing mysql2 alongside mysql, but eventually translated the latter to the former.

NetBeans 6.9.1 + Ruby 1.9.2 + Rails 3.0.0 + Debugging

This fix is for anyone that has NetBeans 6.9.1, Ruby 1.9.2, Rails 3.0.0, already installed, and decides to add support for debugging on Windows XP.

That was my configuration, but it didn’t work properly. A debug session always ended with an error about a non existing script/rails file. After some research, today I discovered this fix that eventually allows me to cleanly debug a Ruby on Rails 3.0.0 project.

ONCE
  1. Download DevKit 4.5.0 from http://rubyinstaller.org/downloads/
  2. Install DevKit as described at http://github.com/oneclick/rubyinstaller/wiki/Development-Kit
  3. Enter the command
  4. Enter the command
  5. Edit the file (Ruby folder)/lib/ruby/gems/1.9.1/gems/ruby-debug-ide19-0.4.12/lib/ruby-debug-ide.rb as follows This one isn’t required, but I find wrong labels very distracting
  6. Edit the file (Ruby folder)/lib/ruby/gems/1.9.1/gems/ruby-debug-ide19-0.4.12/bin/rdebug-ide.rb as follows See also: http://netbeans.org/projects/ruby/lists/users/archive/2010-09/message/25
PER PROJECT
  1. Edit the file (Project folder)/Gemfile as follows
  2. delete the file (Project folder)/Gemfile.lock
  3. Enter the command

That’s all. I hope it’ll work for you too :-)

© 2017 Notes Log

Theme by Anders NorenUp ↑