Older blog entries for shlomif (starting at number 671)

Two Freecell Solvability Report for the First 400,000 Deals

With some help from some people on the fc-solve-discuss list and off the list (namely Amadiro from the University of Oslo and someone else that I met on IRC , I ran my solvers on the first 400,000 Windows Freecell deals with only two available freecells to see how many of them can be solved.

Here is the report:

Start Index End Index Solved Impossible Intractable
1 32,000 25,381 6,619 0
32,001 50,000 14,302 3,698 0
50,001 100,000 39,775 10,225 0
100,001 400,000 238,415 61,584 1 (No. 384243)
Total 317,873 82,126 1

So about 79.47% of the deals can be solved and the rest are impossible. The only intractable deal that none of my solvers could yield a verdict for is No. 384,243, and it spans a very large number of states:

  • The dbm_fc_solver got into Reached 12,821,000,000 ; States-in-collection: 13,620,999,440 before it failed to produce more results due to a limitation of the hardware where it was deployed on.

  • The depth_dbm_fc_solver yielded this:

    Reached 13,763,700,000 ; States-in-collection: 16,226,294,490 ; Time: 1345126456.520408 Queue Stats: inserted=16,226,294,490 items_in_queue=2,462,594,490 extracted=13,763,700,000

    with a curr_depth of 38. However, that solver may have some yet undiscovered bugs.

So what's next? I’d like to investigate some ways to scale to a larger number of states, perhaps by creating a distributed solver. A google search for distributed breadth first search yields some results:

I hope you enjoy the statistics for the time being.

Syndicated 2012-09-02 09:19:00 from shlomif

Bash Function for Caching Results

In this blog I’d like to blog about the newest edition to my Bash (the UNIX shell) aliases file: the cache() function. What it does is cache the result of a lengthy command in a file in a common place, and then simply output this file if it already exists. I found it of use when I compiled a report which involved some lengthy recursive grep operations which were time consuming, and required a lot of waiting. Another upside to caching is the fact that one can monitor its progress by following the file on disk.

Here is the cache function, available under the MIT/X11 licence:

# What this function does is cache the result of a command in a file, and
# use the file to output the results in case it exists.
# Format is: cache "$basename_to_cache_in" $cmd $arg1 $arg2 $arg3...
cache()
{
    local cache_fn="$1"
    shift

    local dir="${CACHE_DIR:-.}"

    if ! test -d "$dir"; then
        mkdir -p "$dir"
    fi

    local fn="$dir/$cache_fn"
    if ! test -f "$fn" ; then
        "$@" > "$fn"
    fi
    cat "$fn"
}

Hope you find it useful.

(Note: part of the reason why I'm writing this post is to see if it shifts away the spam comments from my previous post, which attracted a lot of spam in the past days. It's an experiment to see how spam behaves.).

Syndicated 2012-09-01 15:05:58 from shlomif

Tech Tip: debugging Ruby’s rspec scripts

This post will cover how to debug test scripts (and their equivlent production code) of the Ruby programming language’s RSpec framework using an interactive debugger, which was a problem I've ran into lately when working on some Ruby code. Most of the other posts I found about the topic were either incomplete or out-of-date, but I got some help from #ruby-lang on Freenode, so I was able to figure it out.

What you should do is:

  1. install the ruby-debug gem: gem install ruby-debug.

  2. Add require 'ruby-debug' to the top of the test script.

  3. Add a debugger statement to lines where you want to place a breakpoint. This is important because otherwise the debugger will never stop. (I am unhappy with it.)

  4. Use the --debug flag in rspec: rspec --debug t/parse-board.rb.

After doing all that it worked for me, so now I'm happy.

Copyright and License

The text is copyrighted by Shlomi Fish, and is made available under the Creative Commons Attribution License 3.0 Unported (or at your option, any later version). In order to attribute the text to me (= Shlomi Fish), please link to this page and to my homepage.

Syndicated 2012-08-18 11:13:06 from shlomif

Getting Your Job Ad Replied To

Joel Spolsky had published an essay titled “Getting Your Résumé Read” on his Joel on Software site, which gives very good advice for job candidates who want to apply for work. Today, I am going to cover the opposite direction: give some advice for employers who publish job ads in hopes of finding employees. I have seen my share of bad practises among the many job ads I have read, and can tell which ones make me more willing to apply.

Before I start, I am going to share a small item, which I originally planned to publish as is, and later decided to expand into this post, which I have titled “The Worst Job Offer Ever”. After I wrote it, I thought that posting something like that on my blog will make no one want to hire me ever again, so don’t take it too seriously. I am not singling any particular “wanted” adverts.

From: lamejob@gmail.com
To: programmersforum@yahoogroups.com
Subject: BEST JOB!!!

A promising startup with a young, dynamic, environment is looking for a
talented software developer with the following skills:

* Team-player.
* Independent.
* Detail-oriented.
* Considers the big picture.
* Ability to work under pressure.
* Willing to work for stock options.
* B.Sc./B.A. in Computer Science/Software Engineering or equivalent from a
prestigious university with an average of 93.1415% or above.
** M.Sc. an advantage.
* 10 years of experience in JAVA.
* 25 years of experience in php/Mysql.
* 1-3 years of experience in PERL, PYTHON, ror - an advantage.
* 10 years of OOP/OOD experience in C++ and COBOL - a must.
* windows/unix/LINUX sys admin experience (3-5 years).

Please send your CVs in MS Word format to lamejob-jobs@gmail.com .
--
Sent from my iPhone.

I hope you agree that it is pretty bad. Now for the rest of the advice:

  1. The first thing you should do is to spell the requirements precisely. What does the candidate must know for the job? Please consider avoiding giving a number of years of experience because this is annoying. “1-3 years of Java experience” — are people with 4 years of Java experience underqualified?

  2. You should also give a precise description of the job: something like “Ruby-on-Rails expert”, “Perl expert”, “UNIX Systems Administrator”, “PHP expert” etc. That way people who do not match this description will know better than to apply.

  3. You should also use proper spelling, grammar, and syntax. Perl is not spelled “PERL”, Python is not spelled “PYTHON”, and it's MySQL - not “MYSQL”, “Mysql” or “mySQL”. It's also “PHP” - not “Php” or “php”.

  4. If you have a successful business or planning on having one, then you should get your own DNS domain such as mycompany.com, set up E-mail hosting for it, and send the job posts from there. Sending from a Webmail provider such as “@gmail.com”, “@hotmail.com” or “@yahoo.com” will make a bad impression, and indicate lack of professionalism.

  5. You should also use a standard desktop, or a comfortable laptop computer to type and phrase the message - not a mobile device which results in more error-prone and less Netiquette -conforming messages. Make sure that your E-mail lacks any of the branding or advertising signatures such as “Sent from my iPhone”.

  6. Specify the formats in which it is possible to send the résumé, for example Microsoft Word, OpenDocument Text, XHTML or PDF. This way the candidates will know which formats they should send and you will have less problems reading their E-mails. That is one thing the worst job advert I gave did right, but naturally many people will appreciate the ability to send in different formats to the proprietary Microsoft Word format.

    Also specify whether it would be possible to send a link to an online version of the résumé for easy viewing using your favourite browser, and avoid the hassles of opening attachments and their myriad formats.

  7. Please don't require an “ability to work under pressure”. Most developers are naturally going to perform worse under pressure, and you should make sure you avoid pressuring them as much as possible. In order to attract developers, it is a good idea to advertise that your company normally operates on no more than 40 hours of work in a week — see what Evan Robinson has written about it in “Why Crunch Modes Doesn’t Work: Six Lessons”.

    If you do have a pressured environment (which is unfortunate but a fact of life), say “We have a pressured environment.” instead.

  8. Another good idea is to encourage candidates to show off their open-source projects and web-presence (home sites, blogs, etc.). However, “show me your GitHub page” may work for some people, but will leave a bad taste in the mouth, and will offend some other people, because some people prefer some of its alternatives (include me).

  9. You should spell the location of your offices (at least roughly) and specify how much one can telecommute, if at all.

  10. Whatever you do, please don’t post the job ad to the same forum more than once every few months. Posting the exact same position several times will make people annoyed and they may complain, filter your messages, or request that you get banned from posting on the forum.

  11. It is a good idea to mention some of the software management practices your company employs, such as using version control, writing automated tests, performing code reviews, refactoring, or pair programming.

  12. Finally, as Joel mentions in the original essay, you should make your ad stand out. One good example was once posted to the Israeli Ruby developers mailing list:

    Subject: Developers Developers Developers
    
    Looking for developers who:
    
    * want a full time, salaried position
    * want to work in a fun, young workplace
    * want to work in an environment that allows them to use (just about)
    whatever tools they wish to get the job done
    * know and love ruby
    * ideally have experience with php and python
    * want to work on large scale rails/merb projects that have nothing to
    do with "the social web"
    * want to drown a puppy every time they hear phrases like "the social
    web"
    

    This job ad (and especially the two last items) makes a stance, and makes the readers feel empathic towards it.

  13. Good luck!


Copyright and Licence

This document is Copyright by Shlomi Fish, 2012, and is available under the terms of the Creative Commons Attribution-ShareAlike License 3.0 Unported (or at your option any later version).

For securing additional rights, please contact Shlomi Fish and see the explicit requirements that are being spelt from abiding by that licence.

Syndicated 2012-08-11 11:31:49 from shlomif

Getting Your Job Ad Replied To

Joel Spolsky had published an essay titled “Getting Your Résumé Read” on his Joel on Software site, which gives very good advice for job candidates who want to apply for work. Today, I am going to cover the opposite direction: give some advice for employers who publish job ads in hopes of finding employees. I have seen my share of bad practises among the many job ads I have read, and can tell which ones make me more willing to apply.

Before I start, I am going to share a small item, which I originally planned to publish as is, and later decided to expand into this post, which I have titled “The Worst Job Offer Ever”. After I wrote it, I thought that posting something like that on my blog will make no one want to hire me ever again, so don’t take it too seriously. I am not singling any particular “wanted” adverts.

From: lamejob@gmail.com
To: programmersforum@yahoogroups.com
Subject: BEST JOB!!!

A promising startup with a young, dynamic, environment is looking for a
talented software developer with the following skills:

* Team-player.
* Independent.
* Detail-oriented.
* Considers the big picture.
* Ability to work under pressure.
* Willing to work for stock options.
* B.Sc./B.A. in Computer Science/Software Engineering or equivalent from a
prestigious university with an average of 93.1415% or above.
** M.Sc. an advantage.
* 10 years of experience in JAVA.
* 25 years of experience in php/Mysql.
* 1-3 years of experience in PERL, PYTHON, ror - an advantage.
* 10 years of OOP/OOD experience in C++ and COBOL - a must.
* windows/unix/LINUX sys admin experience (3-5 years).

Please send your CVs in MS Word format to lamejob-jobs@gmail.com .
--
Sent from my iPhone.

I hope you agree that it is pretty bad. Now for the rest of the advice:

  1. The first thing you should do is to spell the requirements precisely. What does the candidate must know for the job? Please consider avoiding giving a number of years of experience because this is annoying. “1-3 years of Java experience” — are people with 4 years of Java experience underqualified?

  2. You should also give a precise description of the job: something like “Ruby-on-Rails expert”, “Perl expert”, “UNIX Systems Administrator”, “PHP expert” etc. That way people who do not match this description will know better than to apply.

  3. You should also use proper spelling, grammar, and syntax. Perl is not spelled “PERL”, Python is not spelled “PYTHON”, and it's MySQL - not “MYSQL”, “Mysql” or “mySQL”. It's also “PHP” - not “Php” or “php”.

  4. If you have a successful business or planning on having one, then you should get your own DNS domain such as mycompany.com, set up E-mail hosting for it, and send the job posts from there. Sending from a Webmail provider such as “@gmail.com”, “@hotmail.com” or “@yahoo.com” will make a bad impression, and indicate lack of professionalism.

  5. You should also use a standard desktop, or a comfortable laptop computer to type and phrase the message - not a mobile device which results in more error-prone and less Netiquette -conforming messages. Make sure that your E-mail lacks any of the branding or advertising signatures such as “Sent from my iPhone”.

  6. Specify the formats in which it is possible to send the résumé, for example Microsoft Word, OpenDocument Text, XHTML or PDF. This way the candidates will know which formats they should send and you will have less problems reading their E-mails. That is one thing the worst job advert I gave did right, but naturally many people will appreciate the ability to send in different formats to the proprietary Microsoft Word format.

    Also specify whether it would be possible to send a link to an online version of the résumé for easy viewing using your favourite browser, and avoid the hassles of opening attachments and their myriad formats.

  7. Please don't require an “ability to work under pressure”. Most developers are naturally going to perform worse under pressure, and you should make sure you avoid pressuring them as much as possible. In order to attract developers, it is a good idea to advertise that your company normally operates on no more than 40 hours of work in a week — see what Evan Robinson has written about it in “Why Crunch Modes Doesn’t Work: Six Lessons”.

    If you do have a pressured environment (which is unfortunate but a fact of life), say “We have a pressured environment.” instead.

  8. Another good idea is to encourage candidates to show off their open-source projects and web-presence (home sites, blogs, etc.). However, “show me your GitHub page” may work for some people, but will leave a bad taste in the mouth, and will offend some other people, because some people prefer some of its alternatives (include me).

  9. You should spell the location of your offices (at least roughly) and specify how much one can telecommute, if at all.

  10. Whatever you do, please don’t post the job ad to the same forum more than once every few months. Posting the exact same position several times will make people annoyed and they may complain, filter your messages, or request that you get banned from posting on the forum.

  11. It is a good idea to mention some of the software management practices your company employs, such as using version control, writing automated tests, performing code reviews, refactoring, or pair programming.

  12. Finally, as Joel mentions in the original essay, you should make your ad stand out. One good example was once posted to the Israeli Ruby developers mailing list:

    Subject: Developers Developers Developers
    
    Looking for developers who:
    
    * want a full time, salaried position
    * want to work in a fun, young workplace
    * want to work in an environment that allows them to use (just about)
    whatever tools they wish to get the job done
    * know and love ruby
    * ideally have experience with php and python
    * want to work on large scale rails/merb projects that have nothing to
    do with "the social web"
    * want to drown a puppy every time they hear phrases like "the social
    web"
    

    This job ad (and especially the two last items) makes a stance, and makes the readers feel empathic towards it.

  13. Good luck!


Copyright and Licence

This document is Copyright by Shlomi Fish, 2012, and is available under the terms of the Creative Commons Attribution-ShareAlike License 3.0 Unported (or at your option any later version).

For securing additional rights, please contact Shlomi Fish and see the explicit requirements that are being spelt from abiding by that licence.

Syndicated 2012-08-11 11:26:00 from shlomif

Tech Tip: How to Build Firefox with Debugging Symbols on Linux

I spent a large part of today building Firefox on one of my Linux machines and trying to figure out why gdb did not display debugging symbols, and instead only displayed question marks in the backtrace (?? ). Eeventually, I found a solution, so I'd like to document the process for other people in the future.

The solution is documented in this bug report that I filed and involves the following steps:

  1. Checkout the firefox source from the mozilla-central repository

  2. Put something like the following in the .mozconfig file in the source's root (where client.mk can be found):

    . $topsrcdir/browser/config/mozconfig
    export LDFLAGS="-Wl,--no-keep-memory"
    mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/ff-dbg
    ac_add_options --disable-optimize
    ac_add_options --enable-debug
    ac_add_options --enable-tests
    ac_add_options --enable-debug-symbols
    ac_add_options --prefix="$HOME/opt/firefox-from-hg"
    

    The important lines are the --enable-debug, --enable-debug-symbols and the LDFLAGS one.

  3. Type make -f client.mk. Now you'll need to wait.

  4. Type make -f client.mk install PKG_SKIP_STRIP=1 and make sure you do not forget the PKG_SKIP_STRIP=1 parameter.

  5. Now you can use gdb ~/opt/firefox-from-hg/bin/firefox to debug Firefox with all the debugging symbols.

Enjoy!

Syndicated 2012-07-04 17:08:20 from shlomif

How to Listen to Jamendo Radio and Tracks from the Browser

In case you do not know, Jamendo is a show case for music licensed under Creative Commons licences, with a lot of great tracks to listen to. However, after the recent upgrade, I found that I was no longer able to listen to their radio stations or press the listen button of their tracks using Firefox, my browser of choice.

Here is what I discovered on how to re-enable it after some investigation: first of all, you need to enable and/or whitelist JavaScript for jamendo.com. If you are using NoScript, you can use the “S” button on the Add-on bar for that.

Furthermore, the new Jamendo requires Adobe Flash to be whitelisted as well. If you are using FlashBlock, then go to “Tools → Add-Ons → Extensions → Flashblock → Preferences → Whitelist” and add http://www.jamendo.com/ there. I don’t know how to properly enable the listening on browsers and platforms which do not have Adobe Flash installed, so blame Jamendo.com - not me. (And, yes, I know that Flash is evil.)

There may be some other obstacles on the way, but now everything is working fine for me. I am going to complain to Jamendo that in this HTML 5 day and age, one needs to use Flash to listen to their streams, which, as I recall, was not necessary in the old Jamendo.

Happy listening.

Syndicated 2012-06-27 11:40:08 from shlomif

New and Updated Material on My Homepage

Here are the recent updates for Shlomi Fish’s Homepage. There are quite a few changes this time.

The humorous document “It’s not a Fooware - it’s an Operating System.”, mostly written by me, was restored from the perl.net.au wiki which is currently down:

Lots of people heard Emacs haters complain that “Emacs is not an editor - it’s an operating system” or something along these lines. So here we're trying to concentrate other such programs that are no longer limited only to their original purpose, but rather expanded to cover lots of other stuff. So you'll know that Emacs is not alone.

I also added a a new aphorism:

We agree. But do we agree to agree?

There are some new Factoids:

If the mountain will not come to Muhammad, then Muhammad will go to the mountain. If the mountain will not come to Chuck Norris, then the mountain will suffer Norris’s wrath for not complying with his whims.

And there are also some new fortune cookies:

  • Su-Shee: SO I TURNED TO YOU FOR HELP IN TIMES OF DESPERATION…
  • Botje: desperation is for wimps
  • anno: prosperation?
  • Altreus: deprecation is an outdated concept and we prefer not to do it
  • Su-Shee: let’s deprecate deprecation.
  • alpha--: agreed.
  • alpha--: oh wait.
  • Su-Shee: that would be a deprecation
  • rindolf: Who will watch the watcher?
  • rindolf: Who will deprecate deprecation?
  • Su-Shee: shouldn’t someone deprecate the deprecator in that case?
  • * rindolf deprecates the deprecator who is deprecating deprecation.
  • Altreus: that's OK, it's not deprecated yet

I found many typos in the fifth part of the Perl for Perl Newbies series before and during giving the talk at the Tel Aviv Perl Mongers and also prepared some notes for it in Hebrew (which can be found in the series’s front page).

The Transcript of the Perlcast interview with Tom Limoncelli, about his book Time Management for System Administrators has been restored from the currently offline perl.net.au wiki:

Josh: Getting back to where we had started on that planning your day at the beginning of the day, before you check your email. You claim there, that whenever you're prioritising your activities, you really only need three categories and not, you know, a top-ten list, or anything like that. Could you explain that a little?

Tom Limoncelli: that comes from the fact that I used to try to really be specific about the priorities of my action items. So I put something in my to-do-list, and I'd say well, you know I'm ranking their importance from 0 is not important, and a 100 is the world is going to explode if I don't do it right now. And I spent so much time calculating "Wow, is this more like a 63 or a 67, is it a 67? Wow!". And I just spent so much time trying to get an exact priority. In some cases, the task would have been done already. You know I've spent too much time prioritising.

I'm not sure where I picked this up, but someone recommended three priorities: A - it's due today; B - it's important; and C - everything else. Generally, if it's a day where I have any A's at all - that's all I'll be working on. And the way projects go, I'm generally working on that for the whole day. So that's sort of the exception. Most of the time I'm working on B's, which are things that are important, and C's are sort of those would-be-nice-kind-of-things.

And the nice thing about breaking it into this a simple A, B, C priority scheme is that first of all, you're spending less time picking your priority. And secondly, when you're planning your day, in that 5-minute planning period, you can look at your tasks and say "You know, I wanna work 8 hours today, I have one hour of meetings, so I'm down to 7 hours", and then you can look at your tasks and say "Is this more than 7 hours worth of work?". Because it's written, I can start actually doing this kind of planning, and say "That's more like 14 hours worth of work, so those C priorities and B priorities - I'm gonna move them to the next day's to-do-list." Or maybe, OK, I have time for my A's and my B's and the C's get moved.

The third version of my essay, “The Case for Drug Legalisation”, is now live, with several major improvements. They are in large part, thanks to someone who commented on my essay, and allowed me to use their text, and who chose to remain anonymous.

I have set up project pages for MikMod, a module files player, which I now maintain, and for Website META Language, a sophisticated HTML preprocessor, which I have also been maintaining and recently released its 2.2.0 version.

Also in the software section is a How to Contribute to my Projects sub-section with a concentrated and ongoing “HACKING” document.

And, naturally, there are also many smaller enhancements, such as new links, fixes for broken links, new <meta name="description" /> tags, and corrections of typos. I’ve also moved the site’s version control repository from a Subversion repository that required a username and password to access to a publicly-accessible Mercurial repository. More details can be found on the Site's Source Code page.

Syndicated 2012-06-14 10:18:07 from shlomif

Freecell Solver 3.12.0

Freecell Solver version 3.12.0 has been released. It is available in the form of a source archive from the download page. Freecell Solver is an open source framework (library and some command line applications), for automatically solving several variants of card Solitaire / Patience games, including Freecell.

The first item to note is that the URL of its site changed from under *.berlios.de to http://fc-solve.shlomifish.org/, and that there is a redirect in place. Moreover, we have switched the version control system from one based on Subversion to a git repository which is currently hosted on GitHub (though we may move it later).

This release adds a new flag - --show-exceeded-limits or -sel for short, that removes some ambiguity in the output, and fixes a problem with starting the solver with --set-pruning r:tf in conjunction with -opt. A new preset - -l three-eighty (or -l te for short) has been added, which provides somewhat better performance.

The experimental dbm_fc_solver is now less experimental and can now store the positions inside binary trees in memory, and its memory consumption has been greatly reduced since earlier versions. We also added another experimental solver called fcc_fc_solver which aims to determine the solvability of a deal by analysing fully-connected-components (“FCCs”).

We also added support for building and testing the distribution in an out-of-tree build, and there are some cleanups to the code.

More information about all these can be found in the distributed documents of Freecell Solver.

Enjoy!

Syndicated 2012-06-13 13:31:00 from shlomif

Tech Tip: GNU tar’s “-a” Flag

On this post to the Mageia development mailing list by Thierry Vignaud, I discovered that GNU tar (at least in recent versions) has an “-a” flag which is useful in conjunction with its “-c” (create new archive) mode. This is because it detects the suitable compression based on the extension and uses the appropriate flag.

So: “tar -cavf myarchive.tar.gz ./mydir/” is equivalent to “tar -czvf myarchive.tar.gz ./mydir/”, “tar -cavf myarchive.tar.bz2 ./mydir/” does the same thing as “tar -cjvf myarchive.tar.bz2 ./mydir/” and so forth. When unpacking archives, you can omit the “-a/-z/-j/-J” flags, because GNU tar will detect the compression of the archive based on the file magic of the compressed formats.

Another useful (and open-source) tool for manipulating tarballs and other archives is patool, but I've been meaning to suggest they do a short-circuiting when converting tarballs from .tar.gz to .tar.xz to .tar.bz2 / etc.

Anyway, enjoy.

Meta

I know I’ve been really negligent with blogging in my blogs lately (which is not good), but don’t worry - I am fine, just busy with a lot of stuff including work work (which gives money but consumes time), doing quite a lot of coding and other development on open-source software, some Freecell-related research, keeping up with my E-mails, posting to mailing lists, playing some computer games, chatting a lot (maybe too much) on the IRC, and naturally - sleeping.

It seems that despite starting the new job in December, and despite the fact that it was now spring time (which is often a time of calamity for me), I did not have any particularly strong periods of stress lately, which is a good think. Thanks, $DEITY!

Today a friend who is an Israeli open-source enthusiast called me and asked me why I disappeared and if everything OK, and I replied, but he later called again and said his mobile phone mixed me with someone else. Anyway, you can always reach me in many ways, but I think I should start blogging more often, so I‘ve picked up this tech tip as the lowest hanging fruit.

Syndicated 2012-05-27 20:38:59 from shlomif

662 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!